How to extend a sandbox's lease
Call sbx.extend(seconds) while the sandbox runs; it moves the end of the lease later, up to an hour ahead of now, as often as you need.
On Runtime the end of a lease pauses the sandbox by default instead of deleting it. Files, memory and running processes are kept, so a job that ran over its time can be woken and finished rather than started again. An extension costs nothing on its own; the extra time is billed as it is used, at $0.03125 an hour for a waiting 2 vCPU, 4 GiB sandbox and $0.08 fully busy (pricing, checked 25 September 2026).
Extend a running sandbox
TypeScriptimport { Sandbox } from "withruntime";const sbx = await Sandbox.create({ timeoutSeconds: 600 });console.log("ends at", sbx.info.expiresAt);await sbx.extend(1800); // 30 more minutes before the lease endsawait sbx.refresh();console.log("now ends at", sbx.info.expiresAt);await sbx.stop();Pythonfrom withruntime import Sandboxsbx = Sandbox.create(timeout_seconds=600)print("ends at", sbx.info["expiresAt"])sbx.extend(1800) # 30 more minutes before the lease endsprint("now ends at", sbx.refresh().info["expiresAt"])sbx.stop()Terminalruntime sandbox extend "${id}" 1800 # prints the new end of the leaseOver HTTP it is POST /v1/sandboxes/{id}:extend with {"seconds": 600}, and
an agent over MCP calls runtime_sandbox_manage with "action": "extend".
When the lease has already ended
With the default onLeaseEnd: "pause", the sandbox is paused, not gone. A
wake gives it a fresh lease, and you choose its length:
TypeScriptimport { Sandbox } from "withruntime";const sbx = await Sandbox.connect(process.env.SANDBOX_ID!);if (sbx.state === "paused") await sbx.wake({ timeoutSeconds: 3600 });await sbx.exec("make test", { timeoutMs: 1_800_000 });Pythonimport osfrom withruntime import Sandboxsbx = Sandbox.connect(os.environ["SANDBOX_ID"])if sbx.state == "paused": sbx.wake(timeout_seconds=3600)sbx.exec("make test", timeout_ms=1_800_000)A request to a paused sandbox also wakes it by itself, with a fresh lease of
its own timeoutSeconds.
Lease settings
| Setting | Default | Range or effect |
|---|---|---|
timeoutSeconds |
1800 | At most 3600: the first lease |
extend(seconds) |
none | Moves the end later, up to an hour ahead of now; repeat as often as needed |
onLeaseEnd |
"pause" |
Or "stop" |
wake({ timeoutSeconds }) |
its own timeout | A fresh lease on every wake |
keepAlive() |
off | Extends from your process so ten minutes remain, once a minute |
persistent: true |
false | Paid only: the lease renews itself on the server while credit lasts |
| Trial | 1800 | Each session up to one hour, within the trial's 50 hours |
The CLI takes --timeout <seconds> and --on-timeout pause|stop on
sandbox create. Python uses timeout_seconds and on_lease_end.
Mistakes to avoid
- Asking for more than an hour at once. The lease can reach at most an hour
ahead of now. For a four-hour job, extend as it goes, let
keepAlivedo it for you, or make the sandbox persistent. - Confusing the lease with a command's timeout.
timeoutMsonexecbounds one command (60 seconds by default, 24 hours at most); the lease bounds the machine. A long command needs both. - Extending past your daily limit. A key with a daily spending limit
refuses an extension past it with
spending_limit_reached(HTTP 402), and the SDK does not retry it (security). - Relying on your process to stop the sandbox. A host-side lease bounds execution even if management is unavailable, so a crashed script still leaves a sandbox that pauses or stops on time. Keep leases short and extend them rather than asking for the maximum by habit.
- Choosing
"stop"for work you might resume. A stopped sandbox is not a backup. Keep"pause"unless the sandbox holds nothing you need.
Related
- Keep a sandbox running for servers and notebooks that run for hours.
- Pause when idle to stop paying while it waits.
- Pause and resume a sandbox by hand.
- Time and lifetime in the sandbox environment guide.
Facts on this page were checked on 25 September 2026.