Your agent runs for six hours, gets three-quarters of the way through a migration, and then the sandbox times out. The next morning you kick off a fresh run and it starts from nothing — no working tree, no half-built index, no memory of what it already tried. The work was never persisted, because the box it lived in was designed to disappear.

This is the gap OpenAI is paying to close: its pending acquisition of Ona (the company formerly known as Gitpod) is explicitly about giving Codex — now cited at roughly 5 million weekly users — persistent cloud sandboxes so agent tasks can run for hours or days without your laptop staying awake. But you don't need to wait for that deal to close. The tools already exist. You just have to stop confusing three things that look similar and behave nothing alike.

The short version: Keep code and artifacts on a persistent volume (the durable layer), use snapshots for reproducible checkpoints you can fork from, and use pause/resume only to save cost between work bursts. Never treat the in-sandbox filesystem as your source of truth for multi-day work — it has a deadline.

The three models founders confuse#

Ephemeral code execution is not a persistent workspace. "It saved my files when I paused it" and "my data will still be here next week" are different guarantees backed by different mechanisms. Here are the three, concretely.

1. Pause / resume — same box, fast restore

Pausing suspends one specific sandbox and freezes both its filesystem and its memory — running processes, loaded variables, the lot. When you resume, you're back in that same box where you left off. On E2B this is genuinely fast: resume from a paused sandbox takes about one second (pausing costs roughly 4 seconds per GiB of RAM, since it has to write memory out).

Here's the verified E2B flow (Python). pause() saves the state; connect() reattaches to the same sandbox and auto-resumes it if it was paused:

from e2b import Sandbox

# Start a box and do work
sbx = Sandbox.create()
sandbox_id = sbx.sandbox_id

# Pause between work bursts — saves filesystem AND memory
sbx.pause()

# ...hours later, resume the SAME box (auto-resumes if paused)
sbx = Sandbox.connect(sandbox_id)

You can also let a box pause itself on timeout, and drop memory to keep only the filesystem so resume cold-boots cheaper:

sbx = Sandbox.create(
    timeout=3600,
    on_timeout={"action": "pause", "keep_memory": False},
)

The catch: pause is not forever. A running E2B session is capped by tier (about 1 hour on Hobby, up to 24 hours on Pro), and a paused sandbox is retained for up to 30 days before its data is deleted. Pause is for coming back to a session, not for archival.

2. Snapshot / fork — an immutable checkpoint you branch from

A snapshot is a saved point-in-time image. The trap is assuming "restore" means "resume my box." On Modal it doesn't. Modal captures a Sandbox's filesystem and memory, but restoring produces a new Sandbox that is a clone of the snapshotted state — you create it with Sandbox._experimental_enable_snapshot=True, call ._experimental_snapshot() to get a SandboxSnapshot, and later call Sandbox._experimental_from_snapshot() to spin up a fresh box from it. (Method names are experimental/preview; check Modal's docs before you ship.)

That distinction matters operationally. A fork means you can branch: check the agent's work at hour 4, then launch three variants from that exact checkpoint. It also means the original box you snapshotted is gone unless you kept it — the snapshot is the artifact, the box is not. Modal memory snapshots also expire (7 days) while filesystem snapshots persist as diffs from the base image.

Pause resumes a box; snapshot restores a copy. If your recovery plan assumes the original box comes back, you don't have a recovery plan.

3. Persistent volume — data that outlives every sandbox

This is the durable layer, and the one founders skip. A persistent volume is storage that exists independently of any sandbox lifecycle. You mount it into a box, read and write at the mount path, and the data survives when that box is paused, snapshotted, or destroyed. One volume can be attached to many sandboxes over time — so tomorrow's fresh box picks up exactly where yesterday's left off.

E2B ships this (currently private beta): SDK-managed volumes you mount into sandboxes, with data that persists across sandbox instances. Fly takes the same shape from the VM side — a Fly Machine's root filesystem is ephemeral and meant to be rebuildable, while Fly Volumes are the persistent storage whose data survives stop, suspend, resume, and cold starts. Fly's newer Sprites push this further for agents: persistent VMs that idle to stop billing while preserving state, so an agent can come back to a pull request without rebuilding its environment.

Daytona sits at the other default. Its sandboxes are persistent and stateful out of the box — closer to a Codespace, alive until you delete them — though they auto-stop after ~15 minutes idle and auto-archive after 7 days stopped. If your mental model is "the workspace just stays," Daytona matches it; E2B and Modal make you opt in.

The rule founders can copy#

Pick your durability first, your convenience second:

  1. Source of truth → persistent volume. Code, artifacts, the agent's working tree, its scratch state — anything a multi-day run depends on gets written to a mounted volume, never to the box's own root.
  2. Checkpoints → snapshots. Take a snapshot at meaningful milestones so you can fork, compare, and roll back. Remember restore may hand you a new box.
  3. Cost control → pause/resume. Between bursts, pause to stop paying for idle compute — but treat every paused box as disposable, because tier limits and retention windows will eventually collect it.

The single sentence to tattoo on the runbook: the in-sandbox filesystem is scratch space with a deadline. Everything you'd cry about losing lives on the volume.

If you're still choosing a platform, start with the full sandbox comparison. If the agent is running code it didn't write, read how to run untrusted agent code safely before you mount anything valuable. And if you're still deciding how the agent should run at all, the background vs. synchronous call and the Devin vs. Codex vs. Cursor vs. Jules breakdown are the two decisions upstream of this one.