Skip to content

Sandbox lifetime

Last updated View as MarkdownAgent setup

A Linux sandbox has three parts: a name, a Durable Object, and an instance in Containers. Your Worker reaches the sandbox by name, the name reaches the Durable Object, and the Durable Object starts the instance. The name and the Durable Object last as long as your application uses them. The instance runs only while something keeps it running.

This page follows a coding agent. The agent clones a repository, installs its dependencies, edits files, and starts a development server. Then it waits an hour for its next instruction and reaches the same sandbox by name. The files are still there if the instance kept running or the application saved a snapshot. The development server is still there only if the instance kept running.

Instance running
The Linux instance runs a development server and holds the repository and edits on its disk.

The name and the Durable Object remain

Your Worker calls getByName() with the sandbox name. The same name always reaches the same Durable Object. Durable Object storage keeps data such as session details or a snapshot ID, whether or not an instance is running.

When work arrives and no instance is running, the Durable Object starts one with this.ctx.container.start().

Activity keeps an instance running

An instance keeps running while its Durable Object is active. The Durable Object is active while it handles a request, runs an alarm, streams a response, or keeps an accepted WebSocket open. An open terminal keeps a sandbox running this way, even when nobody types.

After the Durable Object becomes inactive, the instance keeps running for the time set with setInactivityTimeout(), up to 6 hours. A request that arrives within that time reaches the same instance, with its files and processes. When the time ends, Cloudflare stops the instance. Without a timeout, Cloudflare stops the instance shortly after the Durable Object becomes inactive.

A pending monitor() call keeps the Durable Object in memory, so the inactivity timeout starts only after the Durable Object leaves memory. When it leaves, the call ends, so monitor() does not report the stop that follows.

Code that runs inside the instance does not count as activity. If no requests arrive, the instance stops when the inactivity timeout ends, even while a build, a test suite, or an agent task still runs inside it. A Durable Object alarm that runs more often than the timeout and checks the work keeps the instance running until the work ends. Run background processes uses an alarm that runs every minute.

The timeout does not survive a restart

A Durable Object can restart while its instance keeps running, for example after a deploy or between two alarms. The restarted Durable Object starts without an inactivity timeout, so the instance stops shortly after the Durable Object becomes inactive.

The sandbox examples set the timeout after start(), and set it again in the constructor of the Durable Object when the instance is already running. For an example, refer to setInactivityTimeout().

What stops an instance

An instance stops when one of these happens:

  • The inactivity timeout ends.
  • Your Worker calls destroy().
  • The main process exits.

The main process is the entrypoint passed to start(), or the default command of the image. When it exits, the instance stops, and every command started with exec() ends with it. The default command of cloudflare/debian-trixie exits right away, so the sandbox examples start that image with sleep infinity as the entrypoint, or run a web server as the main process.

When the inactivity timeout ends, every process in the instance receives SIGTERM, and Cloudflare stops the instance shortly after, whether or not the processes exit. destroy() stops the instance at once, with no time for processes to clean up. Use SIGTERM only for cleanup that can fail, and save the files you need before the instance stops, for example in a snapshot.

After an instance stops, the next request that calls start() starts a new instance.

Cloudflare does not wake the Durable Object when its instance stops. To record each stop and its reason, refer to Run code when a sandbox stops.

Deploys keep instances running

Deploying a new version of your Worker restarts every Durable Object. A running instance keeps running, and the next request reaches the same instance, with its files and processes. Outbound handlers that the Durable Object set up with interceptOutboundHttp() remain in place and run the code of the new version.

A running instance keeps the image, entrypoint, and environment variables that it started with. start() throws while an instance runs, so a new image or new startup options apply only to instances that start after the deploy. To move a sandbox to a new image, stop its instance, for example with destroy(), and start a new one. The files and processes of the old instance end with it.

Requests, streamed responses, and WebSockets that the previous version was handling end during the deploy. A browser terminal disconnects and must connect again.

After the deploy, the instance keeps running for the inactivity timeout that the previous version set. If no request arrives within that time, the instance stops. The new version starts without the timeout, so set it again in the constructor, as the sandbox examples do.

Container rollouts replace instances only in Container applications that use the default scheduling policy, so no rollout replaces a sandbox.

Files and processes end with the instance

The disk of an instance holds the repository, installed packages, configuration files, and output written by commands. Its memory holds running processes, open terminals, and network connections. All of it ends when the instance stops. The next instance starts from its image, or from a snapshot.

Snapshots carry files to the next instance

snapshotContainer() saves the writable root filesystem of a running instance. It does not save separately mounted filesystems, memory, or processes. Starting with a snapshot creates a new instance with the saved files, and the new instance runs its entrypoint. The processes that were running do not continue. The new instance reuses the same process IDs, so a process ID saved in a file can belong to another process after a restore. Files in /run are in memory, and a snapshot does not save them.

Cloudflare does not restore a snapshot on its own. Your application decides when to save a snapshot. It stores the snapshot, for example in Durable Object storage, and passes it to the next start(). Changes made after the last snapshot exist only in the current instance, so save another snapshot before the instance stops.

A snapshot expires 30 days after it is created or last restored. To keep files longer, copy them to a bucket.

The repository, dependencies, and edits of the coding agent return from a snapshot. The development server does not, so the agent starts it again. To save and restore a workspace, refer to Save and restore a sandbox with snapshots. To save a sandbox each time it stops for inactivity, refer to Save a sandbox automatically.

Mounted buckets outlive every instance

Files in a mounted R2 bucket are objects in that bucket. They remain after every instance stops, and other sandboxes and Workers with access to the bucket can read them. A snapshot does not include mounted directories, and a mount ends with its instance, so each new instance mounts the bucket again.

Use a snapshot for files that belong to one continuing workspace. Use a bucket for files that other systems read, or that must outlive the workspace. To mount a bucket, refer to Mount an R2 bucket.

Was this helpful?