Clusy
All writing

Portal is live

Portal runs long Python jobs on cheap spot machines in your own clouds. If the cloud takes a machine back, the job doesn't die with it: you pick it up on another machine, even on another cloud, from where it stopped.

We launched Portal on Friday. The easiest way to explain why is a job we ran a couple of days before.

We wanted to look at twenty years of the planet's hourly air temperature (ERA5, 2005 to 2024) all at once, in memory, on one machine. That's 267 GB of files, which turn into a 728 GB array once loaded. We ran it on an AWS spot machine at $3.13 an hour. With 42 minutes of loading and 5 of analysis, the whole thing came to $2.52. The same machine on demand would have cost $8.79. (In case you're curious: in 79% of the planet's grid cells, the last ten years had more heatwave days than the ten before.)

The catch is that spot machines are a cloud's spare capacity, and the cloud can take them back whenever it likes. On AWS you get two minutes' warning. If you're 40 minutes into building a 728 GB array, two minutes doesn't help much. The job dies, and you start again.

So in practice people run long jobs on demand and pay full price. Portal is our attempt to fix that.

A job moving between machines, on the Macintosh from portal.clusy.io.

What Portal does

Portal runs your Python scripts on machines in your own cloud accounts: AWS, Google Cloud, Azure, Modal and Lambda. When a spot machine gets its warning, Portal pauses your program between two statements, saves everything it's holding in memory, and suspends the job. When you resume it, on whichever machine you choose, it carries on from the next statement. Nothing it already did has to be done again.

The rest is what you'd hope for. Before anything starts, Portal compares prices across the clouds you've connected, and you pick the machine. While the job runs, it keeps looking for a cheaper machine and moves the job there when the saving is worth it (at least 20%, and at least three times what the move itself costs). If the job runs out of memory inside one of your loops, Portal catches it, saves the job, and lets you resume on something bigger. And every machine it starts has a hard stop, so you won't find one still billing you a week later.

The machines are in your accounts, and your cloud bills you for them as it always has. Where the cloud supports it (AWS, Azure and Google Cloud), Portal connects with a role or a federated credential, so there's no key sitting on our side for anyone to steal.

Portal is designed to be used through a coding agent. You paste one line into Claude Code, Codex, Cursor or VS Code:

set up https://portal.clusy.io/SKILL.md

The agent installs Portal, asks you to sign in with your Clusy account, and walks you through connecting your clouds, checking with you before each step. From then on you can say something like "run this on the cheapest GPU that fits", and it compares the prices and launches it. If you'd rather do it yourself, there's a CLI, and a console at portal.clusy.io/app.

Where it came from

The mechanism behind Portal started with the people using Clusy Notebook. They trained models in their notebooks, and the machine they started on often wasn't the right one for the whole session. They'd prepare data on a CPU, need a GPU to train, then need a bigger GPU once the model outgrew the first one. Every switch meant restarting the kernel and rebuilding everything that had been in memory, which could be hours of work.

So we built a way to move a running notebook session to different compute, with its memory intact. We called it SOMA, which is also the name of the neighbourhood (and the motel) in San Francisco where we lived for a while. Eldar wrote about the idea last month in Towards Fluid Compute. It has run under more than 10,000 Clusy Notebook sessions so far.

Once it worked for notebooks, the obvious next question was why it should stop there. Any long Python job has the same problem, whether it's training, a simulation or a big data pipeline. Portal is that mechanism on its own, for any Python script, on clouds you already pay for.

How the move works

The usual ways to protect a long job both have problems. You can write your own checkpoints, but they only save what you remembered to save, which is usually the model weights and not much else. Or you can snapshot the whole virtual machine, but then you can only restore it onto the same kind of machine.

Portal does it from inside Python instead. It saves your variables, arrays and tensors, the functions and classes you defined, where each loop had got to (iterators, DataLoaders, even tqdm bars), the random number generators, and the files in your working directory. On the next machine it puts all of that back, moves tensors onto the GPU if there is one, and compares every value with a fingerprint taken before the move. If anything doesn't match, the new machine doesn't take over.

That check has already earned its keep. While we were building Portal, it caught a bug of ours in how views of the same array were restored. The move refused to go through, and the original job reopened with everything where it had left it.

Because none of this is tied to the machine, the next one can be quite different: x86 or Arm, GPU or CPU, a VM or a container, on any of the clouds.

"It didn't crash" is a low bar, so we tested something stricter. We trained a small vision transformer and moved it twice mid-training, from an L4 on Modal to an L4 on AWS and back again. Its final weights were identical, bit for bit, to those of a run that never moved. In another test, one training run passed through six machines before it finished: GPUs on Modal, AWS and Lambda, then a microVM, a Docker container, and finally a Mac.

Speed matters most when a spot warning arrives, because the save has to finish before the machine goes. Before launch we set off five real spot interruptions on AWS, on a 560 MB data analysis and a 1.5 GB GPT-2 training run. Each time, the state was safely in S3 between 4.7 and 10.3 seconds after the warning, out of the 120 seconds AWS gives you.

Five spot interruptions on AWS, triggered with its fault injection service, on a 560 MB data analysis and a 1.5 GB GPT-2 training run.

Five jobs in one night

Before asking anyone to trust Portal with their work, we wanted to see it carry some real work of our own. So one night last week we ran five jobs across AWS, Modal and Lambda, each on the cheapest machine that fit. The temperature analysis was the first. The others:

  • A simulation of a billion particles of dark matter settling into the cosmic web, from the early universe to today, on 64 vCPUs. It ran for 2 hours 16 minutes on spot and cost $4.61, against $9.58 on demand.
  • Every ship position reported in US waters from July to December 2024, 1.57 billion of them from 80,593 vessels, turned into the map below. That one cost $0.95.
  • The human proteome, folded. ESMFold predicted structures for 16,650 human proteins, split into eight shards on GPUs at Modal and Lambda, and none failed. It cost $162.55, where the same GPU hours at AWS list prices would have been $222.98.
  • A copy of the ships job that we moved while it ran: 100 seconds in, from an AWS spot machine to a GPU machine on Lambda, and four minutes later back to AWS. It kept 411 million positions in memory through both moves, didn't lose a step, and the whole run cost 78 cents.
Vessel traffic in US waters in 2024: 1.57 billion AIS positions drawn as light on a dark map
1.57 billion ship positions, July to December 2024, from one spot machine that cost $0.95.
The cosmic web at z = 0: a slab of the simulated box, filaments and knots of dark matter
A slab of the billion-particle universe as it stands today.

The whole night cost $203, and the jobs on spot came out 60% cheaper than the same machines on demand. The numbers come straight from the run records, and the case studies go through each one properly.

Where we want to take it

Writing code keeps getting cheaper. An agent can write a training script in a minute. What it can't give you back is the hours that script has already spent running: the data it has loaded and the model it has half trained. The easier code gets to produce, the more of a piece of work's value sits in the state of the running program, and today that state has no life of its own. It lives in one process on one machine, and when the machine goes, it goes too, unless someone has built their own way to save it.

We think a running program's state deserves to be a thing in its own right, something you can keep and pick up somewhere else, the way you already can with code or a container image. That's what a Portal checkpoint is: a capsule of everything the program has built up, in a form that doesn't care which machine it came from. Today Portal uses it to move a job and to resume one after an interruption. Over time we'd like you to be able to fork a running job and try two things from the same point, or hand it to a colleague to carry on from where you are. Clusy Notebook already forks a session's memory into branches, and we want the same for any program.

The longer goal is for a program not to belong to any particular machine at all. The chip, the GPU, the kind of virtualization and the cloud underneath it should be choices you can change while it runs, not something you decide once at the start and live with.

What it can't do yet

That's where we're headed. Today Portal has real limits, and you're better off knowing them before your first run than finding them during it.

It runs Python scripts, not notebooks, on Python 3.12 to 3.14. The CLI works on macOS and Linux, and on Windows through WSL.

It can't save things that only make sense inside a running process: an open file, a socket that's in use, a thread, a child process. If your job holds one, Portal won't move it, and it tells you which variable is the problem. It checks for this every ten minutes, so you hear about it while the job is running rather than when a warning comes in. Your program also has to reach a point where it can pause, between statements in your own code, so a single long call into C or CUDA has to finish first.

Not every cloud gives you two minutes. Azure spot VMs give 20 seconds and Modal GPUs 5, which isn't enough for a big job, and Portal warns you when that's the case. Lambda and on-demand machines give no warning at all.

When a warning does come, Portal saves the job and then waits for you. It won't pick another machine and start spending your money on its own. We think that's the right default, but it does mean someone, you or your agent, has to resume it.

And if you resume on a different GPU model, results can differ in the last few bits, the same as they would without Portal.

The docs list every limit, with the numbers.

Try it

Portal is open to anyone with a Clusy account and a verified email. Paste the line above into your coding agent, or install the CLI:

curl -fsSL https://gateway.clusy.io/install.sh | sh

If you'd like Portal running inside your own cloud account for your team, with your own clusters in the same console, talk to us.

And please tell us what you run on it, especially if something breaks: hi@clusy.io.