Triage Factory performance
Sandbox Performance & Capacity

Capacity,
measured

Every run gets its own gVisor sandbox, network namespace, and private subnet — and the whole apparatus idles at 24 MB and a quarter of a second per run. What binds a host depends on what your agents do: a triage fleet reaches the architectural ceiling of 256 before it strains anything, a build-heavy fleet is CPU-bound — and past saturation it degrades gracefully instead of failing. All of it measured on the production launch path, under live workloads.

how the sandbox is sealed workload-aware sizing 256 runs per host
256
concurrent runs
per host — the ceiling is architectural, not a resource limit
~250
ms to spawn
subnet, namespace, firewall rules, sandbox boot
~24
MB at idle
one sandbox with the agent tool host resident
0
failures at saturation
even at full CPU saturation, nothing breaks — work slows instead
01 The cost of a run

Workload is the variable.

A sandbox's cost is a function of what the agent inside it is doing. At idle it is the isolation machinery alone. A triage agent — reading, searching, editing, running commands — adds a rounding error. A CI-shaped agent cycling dependency builds and browser-scale test suites is a different animal: modest on average, spiky at peak. Both were measured live, per-run, at the cgroup.

per-run cost by workload · measured at the jail cgroup cycle average burst peak
Per-run sandbox cost by workload, measured at the jail cgroup
WorkloadMemory averageMemory burst peakCPU averageCPU burst peak
Idle floor24 MB0.026 cores
Triage agent (20 tool calls/min)34 MB0.038 cores0.061 cores at 3× cadence
CI build + test cycle101 MB354 MB0.48 cores2.1 cores

The triage workload drives the resident tool host with live bash, file, and search calls. The CI workload cycles a compile-shaped burst (JS compute, process spawns) and a browser-sized memory hold at a 40% duty cycle — averages are what a fleet costs over time; peaks are what you leave headroom for. CPU scales with how busy the agent is: tripling tool-call cadence takes a triage run from 0.038 to 0.061 cores — still noise against a build.

02 Latency under load

Flat to 128 live.

The isolation primitives are constant-time: spawning a sandbox onto a host already running 128 of them costs what it cost on an empty machine — and every sandbox on the host was running a live agent workload while these were measured, not sitting idle for the camera.

median latency vs. live sandboxes · all running agent workloads sandbox spawn one more full run
Median latency in milliseconds by number of live sandboxes, all running agent workloads
Live sandboxesSandbox spawnOne more full run
4171 ms477 ms
8181 ms434 ms
16271 ms453 ms
24272 ms427 ms
32271 ms413 ms
48249 ms446 ms
64266 ms490 ms
96208 ms430 ms
128226 ms401 ms

“One more full run” is the whole lifecycle — allocate a subnet, create the namespace, install firewall rules, boot the sandbox, get a live answer from the agent tool host inside, tear everything down — started while every other sandbox stays busy. Reclaiming a sandbox takes ~47 ms. The ceiling is architectural, not a performance cliff.

03 Sizing a host

Size it to your fleet.

Pick the machine and the work; the measured coefficients do the rest. Capacity is the smallest of three limits — memory, CPU, and the per-host ceiling — and which one binds flips with the workload: triage fleets hit the ceiling, build fleets hit CPU.

the machine & the work

Coefficients are the measured ones: triage sized at a busy 0.061 cores and 34 MB per run, CI at 0.48 cores and 101 MB cycle-averaged. ~2 GB stays reserved for the platform at rest.

expected concurrent agent runs
256 limited by the 256-per-host ceiling

spawn stays ~250 ms at every point on this curve

memory admits
1,867
CPU
524–1,048
per-host ceiling
256
every build at full speed fair-shared · measured healthy to 2×

These are three different kinds of line. Memory and the ceiling are admission limits — past them, runs don't start. CPU is pacing: the solid zone runs every build at full speed, the faded zone fair-shares — builds stretch, nothing fails (measured below) — and past 2× is simply unmeasured, not unsafe.

04 Saturation, tested

Overload is a slowdown, not an outage.

Some hour, every agent decides to build at once and demand outruns the machine. That is a scheduling condition, not a failure mode: bursts fair-share, cycles stretch, everything completes. Verified the hard way — 32 sandboxes phase-locked to fire their builds in the same instant, each demanding ~2.1 cores of a machine with nowhere near that many.

cores each build gets when every jail builds at once
Cores each build receives when every sandbox builds simultaneously
Simultaneous buildsCores per buildDemand vs machineHost CPU peak
82.0717 of 32 cores52%
161.7234 of 32 cores87%
321.0367 of 32 cores97%
host CPU peak
97%
the machine fully committed — by design
failures · errors
0
the worst case is late, never broken
ms · one more run
~307
spawning into a saturated host stays flat

Under total oversubscription the kernel fair-shares: each burst compresses toward one core, cycles stretch, and work finishes late instead of failing. Nothing crashes, nothing is evicted, and isolation latency doesn't move. That's the property that makes sizing to averages safe — the penalty for a hot hour is throughput, never correctness.

Memory failure is contained the same way, at the smallest scope that can absorb it. A runaway command is stopped at its own memory budget and the agent is told why — it retries with a lighter approach while the session keeps its headroom. A run that outgrows its hard ceiling fails inside its own sandbox — resident memory pins at the limit, the allocation errors, and no neighbor ever notices. A leak costs a command, at worst a run — never the host.

05 The ceiling

256 by construction.

The 256-run limit isn't a tunable someone forgot to raise — it falls out of the isolation design. Every run owns a private /24 subnet carved from one reserved /16, so exactly 256 can exist on a host at once. The same structure that makes cross-run snooping impossible at the link layer sets the ceiling.

one /16 · 256 private /24s · one per run
live run · 10.42.N.0/24 free slot

Runs never share a network segment, so there is no bridge to police and no policy to misconfigure — and no 257th slot to hand out. Need more than 256 concurrent agents? Add a host; capacity scales horizontally.

Inside the sandbox →

Figures are medians measured on a commodity 32-core / 64 GB x86 host with a warm sandbox image cache, through the production launch path — capability broker, per-run subnet and namespace, gVisor sandbox, resident agent tool host. Per-run costs are read from each sandbox's own control group, so sandboxing overhead is inside every number. The triage workload issues live tool calls; the CI workload cycles compile-shaped bursts and browser-sized memory holds at a 40% duty cycle. Memory containment is verified with a blast-radius scenario: victim runs driven past their own ceiling pin at the limit and fail alone while neighbor runs take zero errors. Per-run figures exclude the host-side credential proxy (~24 MB per run) and orchestration, which the platform reserve covers. Real runs vary with task, model, and repository; treat the calculator as planning guidance and validate against your own workloads before committing hardware.