On Runtime, a fork copies a live machine, not just its disk. A server that was running in the source is still running in every copy. The snapshot that the fork takes for itself is deleted when the fork ends, and it is never billed. Three waiting 2 vCPU, 4 GiB copies cost 3 × $0.03125, about $0.094 an hour, and nothing more (rates checked 25 October 2026, pricing). Copies start on the source's server while it has room. When that server is full, copies start on another server. The snapshot is copied there first.
Fork a machine with a server running
Start the work once, fork, and each copy carries on from that moment:
TypeScriptimport { Sandbox } from "withruntime";await using base = await Sandbox.create();await base.exec("pip install --quiet requests", { timeoutMs: 120_000 });await base.spawn("python3 -m http.server 8000", { cwd: "/workspace" });const copies = await base.fork({ count: 3, labels: { experiment: "retry-policy" } });for (const copy of copies) { const probe = await copy.exec("curl -s -o /dev/null -w '%{http_code}' localhost:8000"); console.log(copy.id, probe.stdout); // 200: the server came along}await Promise.all(copies.map((copy) => copy.stop()));Pythonfrom withruntime import Sandboxwith Sandbox.create() as base: base.exec("pip install --quiet requests", timeout_ms=120_000) base.spawn("python3 -m http.server 8000", cwd="/workspace") copies = base.fork(count=3, labels={"experiment": "retry-policy"}) for copy in copies: probe = copy.exec("curl -s -o /dev/null -w '%{http_code}' localhost:8000") print(copy.id, probe.stdout) for copy in copies: copy.stop()Terminalruntime sandboxes fork "${id}" --count 3runtime sandboxes fork "${id}" --count 3 --keep-snapshotWith count, fork returns a list. Without it, it returns one sandbox. The
source pauses while the fork captures it. Then the source wakes and is running
again when the call returns. It takes longer the more memory the source holds.
A paused source stays paused.
Options
| Option | Default | What it does |
|---|---|---|
count |
one copy | How many copies: 1 to 100 on prepaid credit, 1 to 4 without credit |
funding |
the source's | Accepted and ignored, as on create |
name, labels |
none | Handles for the copies |
keepSnapshot |
false |
Keeps the fork's snapshot, so you can start more copies later. It is then billed as snapshot storage |
| MCP | — | runtime_sandboxes_fork |
Each copy gets the source's vCPUs, memory, disk and CPU setting (reserved CPU, or a raised floor). It is billed as a create of that size would be.
When a copy fails
A fork that fails after its snapshot returns the error from the failing step.
The copies that did start are listed in details.startedSandboxIds. They keep
running, and billing, until you stop them.
TypeScriptimport { RuntimeError, Sandbox } from "withruntime";const base = await Sandbox.create();try { const copies = await base.fork({ count: 5 }); console.log(copies.map((copy) => copy.id));} catch (error) { if (!(error instanceof RuntimeError)) throw error; const started = (error.details?.startedSandboxIds ?? []) as string[]; for (const id of started) await (await Sandbox.connect(id)).stop(); console.log(error.code, error.hint);}A failed fork is over. Retrying with the same idempotency key returns the same error, so fork again with a new key (idempotency keys).
Limits and refusals
| Case | What happens |
|---|---|
| More copies than the plan allows | invalid_request (400): 100 on prepaid credit, 4 without credit |
| Copies past four at the same time without credit | no_credit_running_limit. More copies than that never fit without credit |
| Copies needing over a quarter of the free memory of each server in the region | no_capacity (503), with how many fit now in details.fits. Fork fewer, or try again later |
| Source with reserved CPU or a floor above 250 | Copies cannot fit the limits without credit, so the fork runs only once the account holds credit |
fork_unavailable (503) |
Turned off there on purpose. Retrying does not help |
| Fork stopped partway, source left paused | The source stays paused. A fork-left-paused notice says how to wake it |
A paid account runs 100 sandboxes at the same time. A fork's copies count toward that limit. A fork that would go past the limit is refused before its source is paused (how many at the same time).
Where forking pays off
- Trying several fixes. A coding agent reaches a failing test with the repo built and the dev server up. It then forks one copy per candidate fix (coding agent sandbox).
- Sampling answers. Run the same prepared environment against several model outputs, and keep the best (RL environments).
- Evaluation episodes. Every episode starts from exactly the same memory and process state (agent evals).
Mistakes to avoid
- Forgetting the copies. Each copy is a sandbox that runs on its own, and it is billed until it stops or pauses. Stop each one when its attempt is done, even after an error.
- Forking for later. Copies start now. To start copies next week, take a
snapshot, or pass
keepSnapshot: true. - Retrying a fork without credit that asks for too many. More copies than the four allowed at the same time without credit never fit, however long you wait. Ask for fewer. An account that holds prepaid credit is not held to the limit without credit.
The idea behind forks is explained in what is a sandbox fork?.
Facts on this page were checked on 26 October 2026.