/learn/microvms-vs-containers
MicroVMs vs. containers vs. gVisor
All three run a workload in something that looks like its own machine. They differ in one thing that matters when the code is untrusted: how much kernel the workload shares with everything else on the host.
The short version
/learn/the-stacks
What sits between the code and the kernel
Read each stack top-down, from the agent's code to the hardware. The question is how many layers are in the way, and whether the kernel at the bottom is one the workload shares with other tenants.
Container
Kernel features- Agent code
- namespaces · cgroups · seccomp
- Host kernel — shared
- Hardware
Fastest to start and densest to pack. The isolation is kernel configuration, so a kernel bug is a tenant boundary bug.
gVisor
Userspace kernel- Agent code
- Sentry — syscalls reimplemented in Go
- Host kernel — shared, narrowed
- Hardware
Intercepts syscalls before the host kernel sees them, which cuts the reachable surface a lot. Still one kernel underneath, and syscall-heavy work pays for the interception.
microVM
Separate kernel- Agent code
- Guest kernel — its own
- KVM · Firecracker · jailer
- Host kernel — not shared with the guest
- Hardware
The guest gets a kernel of its own, so escaping means defeating the virtualization boundary rather than a kernel feature. Costs a boot.
highlighted block = the layer doing the isolating · amber = a kernel shared with other tenants
/learn/escape-history
What a shared kernel has cost
Container escapes are not hypothetical. These are real, patched, and worth reading as a class rather than as individual bugs — each one turned a kernel-level or runtime-level flaw into a tenant boundary failure.
- CVE-2019-5736runc
A container could overwrite the host runc binary through /proc/self/exe and get code execution on the host on the next container start.
- CVE-2022-23651containerd
A crafted image configuration could cause containerd to expose host resources into the container.
- Docker socketConfiguration
Mounting the Docker socket into a container hands it the ability to start privileged containers. Not a bug — a default that keeps getting chosen.
MicroVMs are not CVE-proof
/learn/the-cost
What the separate kernel costs
A microVM boots a kernel, and that is real latency you do not pay with a container. Here is what it measures on our own hardware — and what we have not published yet.
Cold start · boot to agent ready
1404 ms
P50, measured on the development host. A full kernel boot, every time.
Warm pool hit · create
2 ms
Pops a pre-warmed member forked from a snapshot, with its identity reset. The boot already happened.
The warm pool is how the boot cost stops mattering for most requests: members are booted ahead of time, and a create takes one off the shelf. The cold number is what you pay when the pool is empty, and it is the honest number to plan against.
Numbers we have not published
/learn/choosing
Which one you actually want
The boundary should match who wrote the code and who you have to trust. Most teams need more than one of these, for different workloads.
| Workload | Boundary | Why |
|---|---|---|
| Code you wrote, running your own data | Container | The workload is already inside your trust boundary. A kernel-level boundary is the right cost. |
| Multi-tenant workloads you review | gVisor | Narrows the syscall surface substantially without paying for a boot. Syscall-heavy work slows down. |
| Model-generated code, untrusted input | microVM | The code was written by something you cannot review in advance. A separate kernel is the boundary that matches that. |
| Regulated data, host operator untrusted | Confidential VM | Memory encryption plus attestation. Needed when the party running the machine is also outside your trust set. |
standard tier runs Firecracker + jailer on KVM · confidential tier runs directly inside a SEV-SNP CVM
/learn/what-we-run
What we run, specifically
The standard tier is a Firecracker microVM per workspace, started under the jailer — chroot, seccomp, cgroups v2, and namespaces around the VMM process itself. Each workspace gets its own guest kernel. The rootfs boots read-only with a writable tmpfs at /workspace, and both kernel and rootfs are checked against a pinned SHA-256 digest at install.
The guest agent is a small static Rust binary that talks over vsock only. It binds no network interface, by design — there is no listener in the guest for anything on the network to reach.
The confidential tier does not nest a microVM inside a confidential VM, because that is not possible: SEV-SNP strips virtualization extensions from the guest. We verified it on silicon — /dev/kvm is absent and the svm flag is zero on an Azure DCasv5. So that tier runs the workspace directly in the CVM, one CVM per sensitive workspace.
Boot one and time it yourself.
The runtime is Apache-2.0 and the benchmark harness is in the repo. Our numbers should not be the ones you plan against.