Skip to main content
Sailboxes preserve their writable disk, in-memory state, and in-flight network requests across checkpoints and resumes. The examples below assume a running Sailbox sb.
Sail also sleeps a Sailbox on its own once it has been truly idle for a while, and wakes it on traffic or the next operation. Waking takes a few seconds, so you can turn automatic sleep off for a Sailbox, or choose how long it must be idle before Sail sleeps it.
The minimum idle time is a whole number of seconds from 1 through 3600; 0 restores Sail’s default of 30 seconds. See Autosleep.

Limit a Sailbox’s lifetime

Set max_lifetime_seconds when creating a Sailbox to have Sail permanently terminate it after a fixed wall-clock lifetime. The limit starts at the Sailbox’s created_at, after image preparation, and includes waiting for capacity, sleeping, and paused time. Activity and resuming do not reset it. Sail enforces the limit even if your client disconnects or crashes.
Use whole seconds from 1 through 4294967295, or omit the limit for unlimited lifetime. The limit is fixed at creation. Get/list return expires_at (expiresAt in TypeScript), or null for unlimited lifetime. Sail checks expiration about every ten seconds and uses the same cleanup as terminate(). from_checkpoint (fromCheckpoint in TypeScript, box from-checkpoint in the CLI) accepts a separate limit for the new Sailbox; it does not inherit the source’s limit. Checkpoint ttl_seconds controls how long the saved checkpoint remains usable.

Checkpoint

checkpoint() creates a durable checkpoint handle. Running Sailboxes are snapshotted first. Paused and sleeping Sailboxes return a handle to their existing checkpoint without waking.
Call checkpoint() after important setup, such as installing packages, fetching remote data, or writing files. On host failure, Sail restores from the most recent completed checkpoint and does not replay commands that ran before that checkpoint. name labels the handle. A checkpoint lasts seven days unless you set a TTL. Set one when you keep a checkpoint to reuse as a template, so the handle does not expire while you still need it. The returned handle includes the expiry time (expires_at), after which starting a Sailbox from it fails.

Start From Checkpoint

Create a separate running Sailbox from a durable checkpoint handle:
The child restores the memory saved in the checkpoint as well as the writable disk, so processes the original was running continue in the child. Commands you started with exec stop in the child, though their writes up to the checkpoint are kept, and one you started with the background option keeps running there. Start the other commands the child needs again. The child gets new Sail identity and networking. Active TCP connections are reset in the child. A child does not inherit ingress, so add the ports the child should publish with expose.

Checkpoints with volumes

Checkpoints save the Sailbox’s writable disk and memory, not a version of its shared volumes. Children reattach the same volumes at the saved paths and keep each mount’s read-only setting.
  • Volume changes remain shared between the source and its children. Restoring an older checkpoint does not roll back those changes.
  • Mounts added to the source after a checkpoint are not attached to that checkpoint’s children.
  • Copied volume clients are discarded without flushing. Applications must reopen volume files in a child; inherited open file handles are not usable.
  • Existing private bind mounts still refer to the old mount. Recreate them in the child before using the volume through those paths or containers.
  • A deleted or unavailable volume prevents creation of the child.
  • Upgrade older Sailboxes before checkpointing with volumes. Legacy NFS volumes are not supported by this memory-preserving checkpoint path.
Save pending volume writes before checkpointing if the children need them. A checkpoint is not a backup of volume contents.
Sleeping and paused Sailboxes can be cloned too: checkpoint() returns the existing checkpoint handle without waking the parent. Starting multiple children from the same checkpoint reuses the same checkpoint artifacts, so the second and later children avoid re-checkpointing the parent.

Fan Out to Many Sailboxes

Starting many children from one checkpoint is the fast path to a fleet of identical environments, for example agent rollouts, parallel test shards, or grading many submissions at once. Prepare one Sailbox (install dependencies, warm caches, start servers), checkpoint it, then start every worker from that checkpoint instead of repeating the setup in each one:
Use the concurrent forms shown here (.aio twins in Python, promises in TypeScript, joined futures in Rust) so the restores overlap instead of running one at a time, and collect the results per child, as the examples do, so one failed restore does not cost you the children that did come up. Give each child a distinct name. Each child is a full, separate Sailbox: it bills like one and keeps running until it sleeps or you terminate it, so clean up the fleet when the work is done. If one process drives hundreds of Sailboxes concurrently, you can also give the SDK’s thread pool more headroom. See Configuration.

Pause

pause() checkpoints the Sailbox and powers it down until you explicitly resume it:
Use pause when you want to preserve state but do not want the Sailbox to wake on network traffic.

Sleep

sleep() checkpoints the Sailbox and powers it down until network ingress, exec, or an explicit resume wakes it:
Use sleep for idle services that should wake when they receive traffic.

Resume

resume() restores a paused or sleeping Sailbox:
exec and file operations wake a sleeping Sailbox automatically, so binding an existing Sailbox by id does not need an explicit resume in any language.

Sleep Until a Wake

Pass a wake time to sleep() to schedule a wall-clock wake as the Sailbox goes down. When the moment arrives and the Sailbox is still sleeping, Sail restores it:
Each Sailbox can have one scheduled wake at a time. A request earlier than the current scheduled wake replaces it. A later request leaves the sooner wake in place. The call returns the effective wake time (the sooner of the two). Schedule the next wake after the current one happens if you need a series. Calling sleep with a wake time on a Sailbox that is already sleeping just updates the scheduled wake. The CLI accepts a delay like 30m or 2h, or an absolute RFC 3339 timestamp. The wake can happen a little after the time you set, so treat it as approximate. Schedule a minute or two of headroom rather than an exact deadline. Paused Sailboxes only wake on an explicit resume and reject scheduled wakes. Use scheduled wakes for agents and services that sleep between runs and need to be running again at a known time, such as a daily job or a follow-up an agent set for itself.

Upgrade

upgrade() reboots the Sailbox on its same disk onto the latest in-guest Sail agent, picking up new features, fixes, and performance improvements without recreating the Sailbox:
The filesystem is fully preserved. Running processes stop and the Sailbox boots fresh, like a machine reboot. Restart any long-running services afterwards. On a running Sailbox the upgrade applies immediately and applied is true. On a paused or sleeping Sailbox the upgrade is recorded without waking it and applied is false. The upgrade applies automatically the next time the Sailbox wakes. A Sailbox that is already on the current runtime version reports true without rebooting. A Sailbox whose runtime is too old for Sail to resume safely is upgraded automatically the next time it wakes, as if upgrade() had been called on it first. Before a runtime version reaches that automatic-upgrade cutoff, get and list return a deprecation notice with a deadline and upgrade instructions. The CLI and Python/TypeScript SDKs also report the first such notice as a warning once per process (Python emits SailDeprecationWarning through the warnings module). Rust callers can install a callback with sail::set_notice_handler. Treat it as advance notice to schedule upgrade() on your own terms before the deadline. It is not an immediate failure.

Terminate

terminate() permanently destroys the Sailbox:
Termination is not reversible. Use pause() or sleep() when you want to keep the VM state for later.