engineering
One job, one VM: how we isolate CI workloads
Why we do not run CI jobs in containers on a shared kernel, and what that costs us.
Priya Raghavan · Infrastructure · 2026-03-18 · 8 min read
A CI runner executes arbitrary code from your repository with access to your secrets. Container isolation on a shared kernel is not a sufficient boundary for that, because a kernel vulnerability is a tenant boundary vulnerability.
What we do
- Each job gets its own microVM with its own kernel
- The VM is destroyed when the job ends — never reused, never recycled
- Disks are cryptographically wiped rather than detached and returned to a pool
- Cache objects are encrypted per repository, so a cache read cannot cross tenants
- No operator has shell access to a running job VM
What it costs
A microVM boots more slowly than a container starts. We spend real engineering effort on warm pools and snapshot restore to get that back to about three seconds. Containers would be easier and we think the trade is not close.
Your next build could be twice as fast, at half the price
Start free. Migrating away is the same one line, and we publish that diff too.
Related
CI when your teammates are agentsAI coding agents push far more often than humans. Here is how that changes pipeline design and cost control.Why we publish instructions for leavingEvery migration page on this site includes the diff to migrate back off us. Here is the reasoning.What we learned running a million CI jobsQueue time, cache behaviour, right-sizing and the failure modes that only appear at scale.Stop retrying flaky testsAutomatic retries convert a real bug into an intermittent one, and train your team to distrust every failure.