# Sandbox cold start benchmark — Hanzo AI

> Time to a running sandbox by primitive: a V8 context in 0.13 ms, a measured isolate in 0.35 ms and a hanzo-vm microVM in 309 ms — and why the fastest row is not the answer, because an isolate runs JavaScript and cannot run pytest, pip, cargo or a shell.

[Benchmarks](https://hanzo.ai/benchmarks) / Sandbox cold start

measured

# Cold start, by primitive

A V8 context in 0.13 ms, an isolate measured at 0.35 ms rather than cited, and a hanzo-vm microVM in 309 ms — and the reason the fastest row is not the answer: an isolate runs JavaScript and cannot run pytest, pip, cargo or a shell.

harness

[hanzoai/cloud · bench/sandbox](https://github.com/hanzoai/cloud/tree/main/bench/sandbox)

`node sandbox/sandbox.mjs`prints the table on this page — transcribed from bench/README.md, the pass of 2026-09-07

## What is measured

The time from asking for a sandbox to having one that will execute code. Three primitives answer that request in three different ways, and they are not interchangeable: a V8 context is a new heap inside a process that is already running, an isolate is a heap of its own, and a microVM is a kernel started from nothing. Timings are the median of the pass.

## Results

M-series laptop · the pass of 2026-09-07 · median of the pass

primitive

measured here

published elsewhere

what it can run

V8 context

0.13 ms

—

JavaScript, sharing the heap

V8 isolate, isolated-vm 7.0.1

2.79 ms, 1.2 MB

JavaScript, its own heap

hanzo-vm, cold boot

309 ms

E2B under 200 ms · Modal ~1 s · Cloudflare 1–3 s

–

hanzo-vm, from a checkpoint

311 ms

Morph under 250 ms resume · E2B ~1 s from pause

–

The isolate row used to be the context row, and that was wrong in our favour. A `vm.createContext` makes a fresh global inside an isolate that is already running; it is cheap because it shares that heap, which is the one thing an isolate does not do. Reporting the context against a published isolate figure and calling it seventeenfold compared two different primitives. Installing the library the 2.79 ms is attributed to and running it on this laptop puts an isolate at 0.35 ms, under the figure cited at us by eightfold rather than seventeen, and a measurement rather than an argument. It read 0.59 ms here once; five consecutive runs give 0.35 ms, because the first run of a session reads high. The megabyte is V8&#x27;s too: a fresh isolate&#x27;s heap measures 1.00 MiB here, close to the 1.2 MB cited, because that is what any isolate costs including one of ours.

The row that matters for an agent that needs a shell used to be a container started by Docker, and nothing here runs Docker: the builds run buildkit inside a microVM. Measured on the runtime we ship, a hanzo-vm boots in 309 ms, which is slower than the under-200 ms E2B publish for Firecracker. Their figure was taken by other people on other hardware under a protocol we did not run, so it is their claim quoted rather than a matched measurement, which is the reason neither number settles it and not a defence of ours. Starting from a checkpoint costs 311 ms, the same: a checkpoint carries the disk an earlier run left, and the kernel boots either way.

## Why the fastest row is not the answer

An isolate runs JavaScript. It cannot run `pytest`, `pip`, `cargo` or a shell, which is most of what a coding agent is actually asked to do. Putting 0.13 ms and 309 ms in one column invites the reading that the first is the same service two thousand times faster, and it is not the same service. The comparison is per workload: for a JavaScript transform the isolate is the right primitive and the container is waste, and for anything that installs a package the isolate cannot take the job at any latency.

That is also why the table above carries a column for what each primitive can run. A latency table without it is the kind of chart that wins an argument and loses the deployment.

## What this does not measure

Cold start is not throughput. This is the time to the first instruction, on an idle machine, with the image already local. It says nothing about what happens when a thousand sandboxes are asked for at once, and nothing about pulling an image that is not cached — both of which dominate in production and neither of which is on this page.

One machine, one day. A single pass on one laptop, reproducible by one command. Read it as a floor that has been established rather than as a service level, and note that the published figures in the right-hand column were taken by other people on other hardware under protocols we did not run — they are the vendors’ own claims, quoted, not a matched measurement.

It is one of three costs, not the cost. A sandbox is what an agent needs to run a command. What it costs to keep an agent that is doing nothing is [477 bytes and a 0.034 ms resume](https://hanzo.ai/benchmarks/fleet), and what a running agent holds is [601 bytes of heap and 125 ns to spawn](https://hanzo.ai/benchmarks/goroutine). The three are separate measurements with separate commands and they do not add up into a single number.

[← PreviousLive agent footprint](https://hanzo.ai/benchmarks/goroutine)[All Benchmarks Board](https://hanzo.ai/benchmarks)[Next →Inference vs llama.cpp](https://hanzo.ai/benchmarks/inference)

### Related in runtime

[Fleet residency→](https://hanzo.ai/benchmarks/fleet)[Live agent footprint→](https://hanzo.ai/benchmarks/goroutine)

Other benchmarks

[LoCoMo](https://hanzo.ai/benchmarks/locomo) · [MemoryAgentBench](https://hanzo.ai/benchmarks/memoryagentbench) · [LongMemEval](https://hanzo.ai/benchmarks/longmemeval) · [RepoBench-R](https://hanzo.ai/benchmarks/repobench-r) · [LoCoMo · subject scope](https://hanzo.ai/benchmarks/locomo-subject-scope) · [LoCoMo-Conv](https://hanzo.ai/benchmarks/locomo-conv) · [Inference vs llama.cpp](https://hanzo.ai/benchmarks/inference) · [GPQA-Diamond](https://hanzo.ai/benchmarks/gpqa)

harness and the committed table: [hanzoai/cloud · bench/sandbox](https://github.com/hanzoai/cloud/tree/main/bench/sandbox) · `sandbox.mjs` needs a container runtime; `colima start` is enough on macOS
