Skip to main content
Podflare runs each sandbox in a dedicated microVM with concurrent snapshot restore, a warm pool, and copy-on-write rootfs clones. The whole point of that stack is that the latency a customer actually feels is the same order of magnitude as calling a local function — not starting a container.

TL;DR — the headline numbers

Production state, end of Q1 2026, measured over 30 sequential cold-start iterations (matches scripts/bench-reliability.py). Two columns because where your client runs dominates the wall-clock number — your in-cloud agent never pays the residential last-mile tax: Server-side compute is single-digit ms; everything else is the network between you and the nearest region. From an agent running in any major cloud region the full create+exec+close round-trip lands at p50 = 43 ms, p95 = 78 ms — measured from a Podflare host benching against itself, which has the same network shape as any nearby cloud customer. For head-to-head comparisons against E2B, Daytona, and Blaxel, see vs E2B, Daytona, and Blaxel — TL;DR: Podflare wins every percentile (p50 / p95 / p99 / max).
~100 ms full round-trip from a fiber uplink or in-cloud. The 187 ms p50 above was measured from a laptop on residential wifi, which adds ~100–150 ms of last-mile jitter on top of the actual server-side compute (single-digit ms). From a fiber-uplink desktop, a VPS, or another cloud region in the same metro, you can expect the full create + exec + destroy flow to land around 100 ms p50 with similarly tight p95/p99. Reproduce with scripts/bench-reliability.py from wherever your agent actually runs.

Headline: edge-routed hot path

What a long-running agent actually looks like — one Sandbox, many execs. This is the number that matters most.

Hot run_code() — already-live sandbox

A full HTTPS POST /v1/sandboxes/:id/exec with NDJSON streaming back. Python interpreter, vsock marshalling, the works. 46 ms p50 is what an LLM agent loop sees per tool call — measurably faster than E2B (180 ms) and Daytona (182 ms) because we use vsock instead of an in-VM HTTP server.

Full round-trip — Sandbox() → run_code() → close()

100 sequential iterations via api.podflare.ai (Cloudflare Worker → nearest origin, haversine-routed), SDK ≥ 0.0.20. Two vantage points — your real number is whichever matches where your agent runs. Both columns cover create + exec + destroy + 3 HTTPS round-trips. The residential column adds ~100–150 ms of last-mile wifi/ISP jitter on top of the in-cloud number. The in-cloud column was measured benching us-west’s hostd against itself — same network shape as any customer agent running in a nearby cloud region. SDK 0.0.20 defaults to api.podflare.ai, the Cloudflare Worker fronting every region. CF’s edge PoP is usually closer to the caller than any individual region origin — from a US west-coast laptop, the edge is ~5–15 ms away versus ~30–50 ms direct to us-west — and the Cloudflare backbone to origin is cleaner than the public-internet route. Counter-intuitive but reproducible: the “extra hop” is shorter wall-clock than going direct.

Where the p95/p99 fix came from (SDK 0.0.19)

Pre-0.0.19 the same bench showed p99 = 1,741 ms and max = 2,290 ms. That “looked” like public-internet TCP SYN drops (0.05–0.35 % across our hosting fleet get dropped, which Linux turns into 1 s → 3 s → 7 s retransmits). It wasn’t. SDK 0.0.17 tried to fix it by capping the connect timeout at 800 ms with retries=2 on a fresh socket. That backfired on residential wifi: a slow-but-real TLS handshake (900 ms due to noisy local DNS) gets killed at 800 ms, retried (killed again), retried (killed again) — three ConnectTimeouts chained together at ~2.9 s. Self-inflicted. SDK 0.0.19 fixes it properly:
Connect widened to 2.5 s so normal-slow handshakes complete on the first attempt; retries dropped to 1 so a real failure isn’t compounded. Result: p99 went 1,741 → 221 ms, max 2,290 → 475 ms. Reproduce against any blackhole IP:

fork() — the 100 ms primitive

Copy-on-write mid-flight snapshot + reflink rootfs. One parent, N children, each starting from the parent’s exact state. Where the 24 ms goes on the server side: The first fork from a fresh parent pays ~90 ms extra because the parent has been running long enough to dirty ~20 MB of pages — those have to hit disk once. On subsequent forks there’s nothing new to dirty and the snapshot stays in the single-digit ms range.

Under the hood — internal latencies

These are the hostd-local numbers (loopback, no network). They’re what the customer-facing numbers above build up from.

Pool refill: 12 ms

Rootfs clones are metadata-only — no block copy — because of the filesystem we use on the host. On a default filesystem the same step takes 700+ ms; that’s the difference between a warm pool that keeps up and one that doesn’t.

Snapshot-load: 3 ms

Seed memory is shared across every pool VM with page-level copy-on-write, so kernel page cache is hit most of the time. Only pages the child actually dirties get copied out.

Which URL should I hit?

Short answer: just call Sandbox() with no arguments. As of SDK 0.0.20 that goes to api.podflare.ai — the Cloudflare Worker that haversine-routes to the nearest origin. From most caller geographies it’s faster than hand-pinning a region URL, because the CF edge PoP is closer than any individual origin and CF’s backbone to the origin is cleaner than the public-internet route. The full picture, in order of preference: Measured from a California laptop, 100 iterations each, SDK 0.0.20:
The Worker also adds automatic failover on origin 5xx (retries the next-nearest region) and enforces concurrent-sandbox limits server-side with a 10 s KV-cached fan-out. You give up none of that by using the default.

When to override the default

  • Your agent runs in the same DC as a specific region (e.g. a Latitude-hosted worker talking to usw1). Direct skips the ~15 ms edge overhead and the CF backbone hop — both of which are pure latency when you’re already one rack away from the origin.
  • Hard region pinning for complianceSandbox(region="eu") forces traffic to Helsinki regardless of where you’re calling from.

Scaling ceiling (single host)

On our current hardware (AMD EPYC 24-core, 96 GB DDR5): Idle warm VMs use far less RAM than their nominal allocation — Our Pod runtime’s COW + lazy snapshot restore means the guest only commits pages it actually touches. We measured ~40 MB RSS per idle 1 GB warm VM under steady-state, so a 120-warm pool burns ~5 GB of the box’s 93 GB available. The other 88 GB is headroom for on-demand customer creates and Space resumes.

Scaling ceiling (multi-region)

Five regions live today, 544 warm sandboxes ready for instant hand-off across the fleet: Routing happens at the Cloudflare Worker fronting api.podflare.ai: server-side haversine using Cloudflare’s per-request cf.latitude / cf.longitude picks the closest origin. SDK 0.0.20 defaults here — pre-0.0.20 clients with client-side timezone routing still work, but the default has moved to edge-routed because CF’s edge PoP is usually closer to the caller than any individual origin, and the CF backbone to origin is cleaner than the public-internet route. The default can be overridden:
  1. Explicit region="us-east" in the SDK or X-Podflare-Region header in raw HTTP
  2. Explicit /r/REGION/... path prefix (e.g. /r/us-east/v1/sandboxes)
  3. Direct region URL via Sandbox(host="https://use1.podflare.ai")
  4. Automatic Worker failover on 5xx (for create-class requests only)
Add a region → update api-router/src/regions.ts with its coordinates and the Worker picks it up the next deploy. SDK clients learn it via the response endpoint header even before an SDK publish.

Distance routing examples

Today’s numbers

Production state, end of Q1 2026. All five regions (us-west · us-central · us-east · eu · sg) report the same shape: For context vs other AI-agent sandbox platforms, see vs E2B and Daytona — same harness, same machine, same minute. Podflare cold-start is 2.2× faster than E2B and 2.9× faster than Daytona in head-to-head benches.

Roadmap

  • UFFD lazy memory paging — replace eager MAP_PRIVATE mmap on snapshot resume with userfaultfd-served on-demand pages. Estimated 50–100 ms off pool-refill time, gated on real production data (waiting for on_demand_boot_ms_mean from the new pool-stats observability to justify it).
  • Memory prefetch mapping — record the pages a guest touches during cold-start at template-build time, replay on resume in a background thread. Phase 2 after UFFD lands.
  • RAM-backed fork snapshots — fork diff writes hit RAM, not disk.
  • Seed-tree templates — per-workload pre-imported snapshots. The python-datasci template already has pandas + numpy + scipy imported in the REPL before you get the sandbox.
  • us-east region promotion — flip continents: ["NA", "SA"] on us-east in the Worker (currently distance-routed only). Cuts geography variance for east-coast NA callers.
  • In-sandbox envd-compatible API — Drop-in surface for the e2b_code_interpreter SDK so customers can repoint at api.podflare.ai with zero code change.

Compared to what?

V8 isolates (Cloudflare Workers) spawn in ~1 ms with ~1 MB memory. They’re an entirely different product: JS/Wasm only, no native deps, no filesystem, no Python REPL state. Real agents that run pip install scikit-learn && model.fit(X) don’t run in isolates. Container-only platforms without snapshot-restore quote “cold start” times that are really docker run + runtime init. A Python container takes ~500 ms–2 s to become usable. Podflare’s warm pool hit is 10–50× faster and the sandbox is already-ready for run_code. E2B and Daytona are the two other major AI-agent sandbox platforms. We benchmarked all three head-to-head in the same minute on the same machine — see vs E2B and Daytona for the full numbers. TL;DR: Podflare cold-start is 2.2× faster than E2B and 2.9× faster than Daytona, mostly because of our vsock-based exec path (46 ms first_exec vs their 180 ms). What we have that they don’t:
  • ~80 ms fork() — copy-on-write diff snapshot + N parallel microVM spawns. Neither E2B nor Daytona expose fork.
  • Persistent Spaces — freeze-to-disk on idle, resume into a fresh sandbox later. The VM’s running Python process survives. Both competitors only support container-commit-style snapshots.
  • 5-region edge routing with haversine geo + automatic failover. E2B and Daytona are single-region per cluster.

Reproduce the numbers

Every number on this page was produced by the bench script in our repo:
Re-run any time you want to audit the marketing. If our numbers regress, we’d rather you find out than pretend.

Methodology

  • Client: macOS laptop on regular residential wifi (west-coast US). This is not the best case. Last-mile wifi + consumer router buffering add roughly 100–150 ms of round-trip time that isn’t there on fiber-uplink desktops or cloud-to-cloud traffic.
  • Network path (direct): Laptop → TLS → Caddy on usw1.podflare.ai → hostd (Latitude SJC bare metal).
  • Network path (edge): Laptop → Cloudflare edge → api.podflare.ai Worker → origin → hostd.
  • Sandbox: Stock default template. 1 GB RAM, 4 GB rootfs, pool-warm.
  • SDK: podflare==0.0.20 (Python) — defaults to api.podflare.ai, which is Cloudflare-edge-routed to the nearest origin. Single shared httpx Client with connect=2.5 s + retries=1. Connection reuse matches what real agent loops do (they don’t open a fresh connection per exec).
  • N: 5 cold-start iterations end-to-end + 30 hot-exec iterations after one discarded warmup. Median reported. Cold-cold first call preserved (not discarded — it’s a real customer experience).
  • Date: April 2026.
No selective sampling. No “we excluded network jitter.” The script in scripts/bench.py runs every iteration back-to-back and reports statistics.mean + percentiles over the raw samples. If your agent runs on a VPS, a fiber-uplink desktop, or a nearby cloud region, coast-to-coast RTT drops from ~50 ms on wifi to ~20 ms on fiber and ~5 ms inside the same metro. Apply that delta to each HTTPS round-trip in the numbers above:
  • Hot run_code(): 38 ms on wifi → ~15 ms on fiber → sub-10 ms in-cloud
  • Full round-trip: 226 ms on wifi → ~100 ms on fiber → ~30 ms in-cloud
The server-side compute numbers (fork 24 ms, pool hit 6 ms, pool refill 12 ms) don’t change — those are what hostd does regardless of where the client sits. Network is the variable.