Every sandbox comparison opens with cold-start milliseconds, and in an agent loop that is the number that matters least. A sandbox serving a twenty-step agent spends roughly six sevenths of its life idle, waiting for a model to finish thinking — so the question that decides your bill is not how fast it starts but whether you are charged while it waits, and the question that decides your blast radius is what its outbound network does by default. Both answers differ sharply across E2B, Daytona, Modal and Cloudflare, and neither appears in the benchmark tables.
At a glance
Four platforms that all run untrusted agent-written code, built on four genuinely different isolation primitives. The primitive is what everything else follows from.
| Platform | Isolation primitive | Billing shape | Egress default |
|---|---|---|---|
| E2B | Firecracker microVM — separate guest kernel per sandbox. | Per second while the sandbox is alive. | Open; allow/deny lists available, including by domain. |
| Daytona | Container from a pre-warmed snapshot. | Per second while alive; auto-stop and auto-archive to end it. | Governed by a documented network-limits layer; posture varies by tier. |
| Modal | gVisor — a user-space kernel intercepting syscalls. | Per second of active compute; idle is not billed. | Open; block_network and outbound_cidr_allowlist per sandbox. |
| Cloudflare Sandbox | Container attached to a Worker, at the edge. | Container runtime, with sleepAfter ending it (10 min default). |
enableInternet on by default; the Worker in front can mediate. |
Worth noting for context: when OpenAI shipped Agents SDK v2 in April 2026 it came with seven sandbox providers wired in natively — Blaxel, Cloudflare, Daytona, E2B, Modal, Runloop and Vercel. Swapping providers is now close to a configuration change, which makes it easy to pick on the wrong axis and expensive to notice.
The idle problem, with arithmetic
Take an agent doing a data-analysis task: twenty steps, each one a model call of roughly twelve seconds followed by about two seconds of code execution. The sandbox has to exist across the whole thing, because the filesystem and the Python kernel carry state between steps.
That is 280 seconds of sandbox lifetime containing 40 seconds of compute. Under a bill-while-alive model you pay for 280. Under a bill-while-active model you pay for 40. The ratio is seven to one, and it is set by inference latency — a variable you do not control and which grows as reasoning effort goes up. Nothing in the cold-start benchmark predicts it.
Two consequences follow. First, per-vCPU-hour rates are close to meaningless as a comparison unless you normalise them by the billing shape; a platform charging noticeably more per active hour can be dramatically cheaper on an agent workload. Second, the idle share rises with the quality of your model, because better models think for longer. Teams that benchmark on a fast small model and deploy on a reasoning model see the sandbox line move in a direction the spreadsheet did not predict.
The counter-argument is real: a bill-while-alive platform with a short auto-stop interval and a fast resume approximates the same thing, and Daytona's auto-stop and auto-archive controls exist for exactly this. But that is a configuration you have to get right per workload, against a default that costs you money, whereas Modal's model is the default. Defaults determine what most teams actually pay.
Isolation: four different answers to the same threat
The threat is the code, not the user
All four platforms assume the workload is hostile, which is correct: agent-written code is untrusted code even when the agent is yours, because its behaviour depends on inputs — retrieved documents, issue comments, web pages — that you do not control. The differences are in how much of the host kernel the code can reach.
E2B's Firecracker microVMs give each sandbox its own guest kernel, so a kernel exploit has to escape a hypervisor rather than a namespace. Modal's gVisor sits between: a user-space kernel intercepts syscalls before they reach the host, which is a much smaller attack surface than a shared kernel and a larger one than hardware virtualization — and, usefully, it keeps GPU passthrough straightforward in a way microVMs make awkward. Daytona's container-from-snapshot is the fastest to start and the most conventional, which is the trade it makes. Cloudflare's containers inherit the Workers platform's boundaries and, uniquely, put the sandbox at the edge next to the request.
Where the difference actually bites
For most agent workloads the isolation tier is not the deciding factor, and saying so is more useful than pretending otherwise. If your agent runs your own generated Python against your own data in your own account, a container is fine. The tier starts to matter when you are running other people's agents — a multi-tenant product where one customer's prompt injection should not reach another customer's execution — and there the microVM boundary is the one you can put in a security questionnaire without a footnote.
The larger practical constraint is GPU. If the sandboxed work touches a model — running an embedding pass, executing generated CUDA, driving an RL environment — Modal is the platform in this set built for it. The others are CPU-shaped, and that is an architectural fact rather than a roadmap gap.
Lifetime and persistence: what survives between steps
Agent loops need state to persist across model calls, and each platform expresses that differently. This is the axis most likely to force a rewrite if you choose wrong.
Session length. E2B supports long-lived sandboxes measured in hours on paid tiers, which suits a research agent that works on one problem all afternoon. Cloudflare's sandboxes are shaped for shorter interactions and sleep after an inactivity window — ten minutes by default, configurable — which suits a request-scoped code interpreter and does not suit a job that thinks for an hour. Modal and Daytona both let a sandbox live until you end it, with idle timeouts and auto-stop intervals as the safety net.
Filesystem state. Daytona's snapshot model is the most developed here: a point-in-time capture of filesystem, packages and settings that any number of new sandboxes can start from, plus declarative image building from a Dockerfile. If your agent needs a repository already cloned and dependencies already installed, that is the difference between a five-minute setup tax on every run and a warm start — and it matters far more than the cold-start figure it is usually quoted alongside.
Resume semantics. The question to ask each platform is what happens when a sandbox stops and starts again: does the filesystem come back, does the process tree, does an open network connection. The answers differ, and an agent architecture that assumed a live process across a resume will fail in a way that looks like a model regression. Design for the weaker guarantee — reconstruct from the filesystem — and the platform choice stops constraining you.
Egress: the control that matters and the default that is wrong
This is the axis nobody benchmarks and the one that decides what a successful prompt injection can do. If an agent's sandbox can reach arbitrary hosts, then any instruction that reaches the agent — from a scraped page, a dependency's postinstall script, an issue comment — has a channel out for whatever the sandbox can read.
All four platforms now expose a control. Modal takes block_network or an outbound_cidr_allowlist per sandbox. E2B supports allow and deny lists covering IPs, CIDR blocks and domain names, resolving domains via Host-header inspection on port 80 and SNI on 443, and lets you replace the rules on a running sandbox without restarting it — which is the most agent-shaped design of the four, since it lets you widen access for one step and close it again. Cloudflare exposes enableInternet as a switch and, more interestingly, lets the Worker in front of the container mediate outbound requests, so a policy can be code rather than configuration. Daytona documents a network-limits layer whose default posture varies by account tier — check yours rather than assuming.
The uniform problem is that the permissive setting is the default everywhere. A sandbox created with the SDK's minimal constructor can talk to the internet, and the framework integrations that make providers swappable are the layer where this configuration is easiest to leave unset. Default-deny egress with a small allowlist — your package registry, your source host, the one API the task needs — is the highest-leverage control in this whole comparison, and it is one line at construction on three of the four platforms.
The credential half is the same story. A sandbox that holds a long-lived API key with broad scope has already lost the argument, because egress control cannot save you from a key the agent is entitled to use. Narrow, short-lived credentials injected per run are the pair to the egress allowlist; either alone leaves the other's hole open.
When to pick which
| Situation | Pick | Because |
|---|---|---|
| Long agent loops with heavy model latency | Modal | Idle is not billed, so the six-sevenths of the sandbox's life spent waiting is free. |
| Multi-tenant product running other people's agents | E2B | A guest kernel per sandbox is the boundary you can defend in a security review, and the egress rules are the most granular here. |
| Heavy environment setup — repo, dependencies, fixtures | Daytona | Snapshots and declarative images make the warm start the normal case rather than an optimisation. |
| Request-scoped code execution inside an existing Workers app | Cloudflare | The sandbox lives next to the request, and outbound policy can be Worker code instead of configuration. |
| Anything touching a GPU | Modal | gVisor keeps GPU access workable; the others in this set are CPU-shaped. |
| Very high-frequency, very short executions | Daytona | This is the one case where the cold-start number genuinely dominates, and it is the fastest. |
One caveat on all of it: rates and limits move quarterly, and every number quoted anywhere in this comparison should be re-checked against the provider's own documentation before you build a cost model on it. The billing shapes — alive versus active — are architectural and change far more slowly than the rates attached to them, which is why they are the thing to choose on.
FAQ
Does sandbox cold start matter for an agent?
Much less than the comparisons imply. It matters if you create a fresh sandbox per tool call, which is usually the wrong architecture — state between steps is what agents need. It matters a great deal for very high-frequency short executions, which is a different workload. For a normal multi-step agent, environment setup time and idle billing both dominate it.
Is a microVM meaningfully safer than a container for agent code?
Yes, in the sense that a kernel exploit has to cross a hypervisor rather than a namespace. Whether that difference is worth paying for depends on your tenancy: running your own agents on your own data, a container is usually adequate; running untrusted third-party agents side by side, the stronger boundary is what makes the answer defensible to someone else.
What is the single most important sandbox setting?
Outbound network policy. Default-deny with a narrow allowlist bounds what a successful prompt injection can exfiltrate, and it is the only control that still works after the model has been convinced to cooperate with an attacker. Every platform here defaults to permissive.
Can I switch providers later?
The execution API is close to commodity, and framework-level integrations make provider swapping near-trivial. What does not port is anything you built on a provider-specific primitive — snapshots, resume semantics, edge placement — plus your cost model, which inverts when the billing shape changes.
Do I need a hosted sandbox at all?
Not always. A container you run yourself with a locked-down network policy is a legitimate answer for a single-tenant internal agent, and it is cheaper. You are buying provisioning speed, snapshot management and a stronger isolation boundary than you would build; if none of those bind, self-hosting is fine.
Does GPU support change the isolation trade-off?
It does. Hardware virtualization makes GPU passthrough awkward, which is why the platform in this set with the best GPU story is also the one using a user-space kernel rather than a microVM. If you need both maximum isolation and a GPU, expect to pay for it in one or the other.
Further reading
On this wiki:
- Sandboxing & Code Execution — the five independent isolation decisions underneath this choice.
- Sandbox & Isolation Patterns — the architecture layer above the provider.
- Sandboxing & Execution — running a coding agent's code specifically.
- Background Coding Agents — where environment snapshots and egress policy pay off most.
- Scoped Credentials for Agents — the other half of the egress story.