Results
Cold Start Latency
Sequential — runtimes created one at a time:| Batch Size | Samples | Mean | p50 | p95 | p99 |
|---|---|---|---|---|---|
| 1 | 5 | 15.0 ms | 14.9 ms | 15.3 ms | — |
| 10 | 50 | 14.6 ms | 14.4 ms | 15.9 ms | — |
| 50 | 250 | 14.6 ms | 14.3 ms | 16.6 ms | 18.1 ms |
| 100 | 500 | 14.6 ms | 14.4 ms | 16.2 ms | 17.9 ms |
| 200 | 1000 | 14.6 ms | 14.3 ms | 16.1 ms | 19.6 ms |
os.availableParallelism() - 4 runtimes created in parallel (16 on this machine):
| Batch Size | Samples | Mean | p50 | p95 | p99 |
|---|---|---|---|---|---|
| 1 | 5 | 18.4 ms | 15.8 ms | 28.0 ms | — |
| 10 | 50 | 24.4 ms | 23.0 ms | 32.3 ms | — |
| 50 | 250 | 35.0 ms | 35.0 ms | 44.5 ms | 47.2 ms |
| 100 | 500 | 35.1 ms | 35.5 ms | 44.9 ms | 48.7 ms |
| 200 | 1000 | 35.2 ms | 35.1 ms | 44.6 ms | 51.0 ms |
Warm Start Latency
Sequential:| Batch Size | Samples | Mean | p50 | p95 | p99 |
|---|---|---|---|---|---|
| 1 | 5 | 3.0 ms | 3.0 ms | 3.3 ms | — |
| 10 | 50 | 3.1 ms | 3.0 ms | 3.6 ms | — |
| 50 | 250 | 3.1 ms | 3.0 ms | 3.7 ms | 5.0 ms |
| 100 | 500 | 3.2 ms | 3.0 ms | 3.9 ms | 5.7 ms |
| 200 | 1000 | 3.1 ms | 3.0 ms | 3.7 ms | 4.6 ms |
| Batch Size | Samples | Mean | p50 | p95 | p99 |
|---|---|---|---|---|---|
| 1 | 5 | 3.6 ms | 3.3 ms | 5.3 ms | — |
| 10 | 50 | 5.8 ms | 5.8 ms | 7.8 ms | — |
| 50 | 250 | 10.2 ms | 10.2 ms | 13.3 ms | 16.0 ms |
| 100 | 500 | 10.4 ms | 10.2 ms | 15.9 ms | 20.7 ms |
| 200 | 1000 | 10.7 ms | 10.4 ms | 15.1 ms | 23.2 ms |
Memory Overhead
| Batch Size | Iterations | Total RSS Delta | Per-Runtime RSS | Per-Runtime Heap | Teardown Reclaimed |
|---|---|---|---|---|---|
| 1 | 5 | 6.1 MB | 6.1 MB | 0.25 MB | 2.3 MB |
| 10 | 5 | 41.9 MB | 4.2 MB | ~0 MB | 24.0 MB |
| 50 | 5 | 170.8 MB | 3.4 MB | ~0 MB | 120.8 MB |
| 100 | 5 | 303.9 MB | 3.0 MB | ~0 MB | 241.4 MB |
| 200 | 5 | 609.7 MB | 3.1 MB | ~0 MB | 483.0 MB |
Methodology
Cold Start
Time fromnew NodeRuntime() through the first runtime.run() completing. This captures
V8 isolate creation, context setup, bridge installation, module compilation, and initial
execution. A trivial ESM module (export const x = 1) is used so the measurement reflects
pure runtime overhead without workload noise.
Each configuration runs 5 iterations (× batch size samples each) with 1 warmup iteration
discarded. Tail percentiles at small batch sizes (≤10) have low sample counts and should be
interpreted with caution.
Sandbox provider comparison uses the p95 TTI (time-to-interactive) from ComputeSDK benchmarks. As of March 2026, e2b is the best-performing sandbox provider at 0.95s p95 TTI.
Warm Start
Time for a secondruntime.run() on an already-initialized runtime. The V8 isolate is
reused, but a fresh V8 context is created and all bridge globals (console, require, import,
process) are re-installed. Module caches are cleared between runs. The difference between
cold and warm start (~12 ms) isolates the cost of new ivm.Isolate().
Memory Per Instance
RSS (Resident Set Size) delta per live runtime, measured viaprocess.memoryUsage().rss
before and after spinning up N runtimes. Testing in batch averages out per-process fixed
costs. Each batch size runs 5 iterations. GC is forced (two passes) between measurements
(--expose-gc).
RSS is a process-wide metric that includes JS-side wrappers, thread stacks, and OS-mapped
pages beyond the isolate itself — the reported per-runtime figure is an upper bound on
the true per-isolate cost.
Sandbox provider comparison uses the minimum allocatable memory across popular providers (e2b, Daytona, Modal, Cloudflare) as of March 2026. The minimum is 256 MB (Modal and Cloudflare).
Cost Per Second
See the cost evaluation for full methodology and multi-provider comparison.Test Environment
| Component | Details |
|---|---|
| CPU | 12th Gen Intel i7-12700KF, 12 cores / 20 threads @ 3.7 GHz, 25 MB cache |
| Node.js | v24.13.0 |
| RAM | 2× 32 GB Kingston FURY Beast DDR4 (KF3200C16D4/32GX) |
| RAM rated | 3200 MHz CL16, dual-rank |
| RAM actual | 2400 MT/s |
| OS | Linux (kernel 6.x) |
| Timing mitigation | "freeze" (default) — Date.now() and performance.now() are frozen inside the isolate; host-side performance.now() used for measurement is unaffected |