Firecracker vs. Other VMMs
This is the reference you cite when someone asks "why not just use QEMU?" — or when you have to justify, in a design discussion, why a proposed feature belongs (or doesn't) in a VMM whose entire thesis is do almost nothing. It places Firecracker against the rest of the isolation landscape: QEMU, Cloud Hypervisor, gVisor, Kata Containers, runc/containers, and unikernels. The big table is the scannable core; the prose after it explains the trade-offs and where each option actually fits.
Reach for this when you are writing a design justification, reviewing a PR that adds device surface area (minimal-device-model philosophy), or placing Firecracker for a colleague who only knows containers.
Warning: Numbers here are order-of-magnitude and version-sensitive — boot times and memory overheads depend on kernel, config, and workload, and the other projects evolve independently. Cite the shape of the comparison ("microsecond-scale device model, single-digit-MiB overhead, KVM boundary"), not a specific millisecond. Firecracker's own headline claims (≤125 ms to app code, <5 MiB overhead/microVM, >20x oversubscription tested) come from the NSDI '20 paper; verify against the current
docs/andFAQ.mdon your branch.
The two questions that organize everything
There are really only two axes, and every row in the big table is a position on them:
- What is the isolation boundary? A hardware-virtualization boundary (a real VM, guest kernel included, behind VT-x/AMD-V/ARM-EL2) — or a software boundary (shared host kernel + namespaces, or a userspace syscall-intercepting "kernel")? This decides how strong the isolation is against a hostile guest.
- How much machine does the VMM emulate? A full PC (BIOS, PCI, USB, dozens of devices, many architectures) — or the bare minimum a Linux guest needs to boot and do I/O? This decides boot time, memory overhead, and — critically — attack surface, because every emulated device is privileged host code a malicious guest can attack.
Firecracker's answer is hardware boundary + almost no machine. That single combination is its whole identity, and it's what the table below makes concrete.
software boundary hardware (VM) boundary
(shared/userspace kernel) (KVM / hypervisor)
full machine ┌── QEMU ───────────────┐
│ Cloud Hypervisor │
─────────────────────────────────────────────────── ├────────────────────────┤
minimal runc/containers gVisor │ Firecracker (Kata can│
machine (namespaces) (Sentry, userspace) │ sit under Kata) │
└────────────────────────┘
The full comparison
| Dimension | Firecracker | QEMU | Cloud Hypervisor | gVisor | Kata Containers | runc / containers | Unikernels |
|---|---|---|---|---|---|---|---|
| Isolation model | KVM microVM, minimal devices; guest kernel untrusted | KVM (or TCG emulation); full machine | KVM / MSHV; rust-vmm | Userspace kernel (Sentry) intercepts syscalls; no HW-virt by default | OCI container inside a lightweight VM | Linux namespaces + cgroups; shared host kernel | App + library-OS as one image, in a VM |
| Boot time | ≤125 ms to app code | 100s ms – seconds (firmware/PCI probe) | sub-second | container-class (no VM boot) | ~100s ms (VM + agent + container) | fastest (no kernel boot) | very fast (tiny image) |
| Memory overhead | <5 MiB / microVM | ~100+ MiB (firmware, fuller device model) | ~10+ MiB | tens of MiB (Sentry process) | VMM + guest kernel + agent | lowest (just the process) | low (no general-purpose OS) |
| Device model | virtio-MMIO net/block/vsock/balloon/rng, serial, i8042-reset; no BIOS/PCI-legacy/USB/GPU | huge: PCI, USB, GPU, SCSI, firmware, many archs | moderate: virtio-PCI, ACPI, hotplug, VFIO passthrough | n/a (intercepts syscalls, not devices) | inherits its underlying VMM's | host devices directly | only what the app links |
| Transport | virtio-MMIO default (virtio-PCI behind --enable-pci) | virtio-PCI, emulated legacy buses | virtio-PCI | n/a | inherits VMM | n/a | varies |
| Language | Rust (memory-safe) | C | Rust | Go | Go (+ its VMM) | Go / C | varies (C, OCaml, Rust, …) |
| Device/CPU hotplug | limited (memory hotplug emerging — verify) | extensive (CPU/mem/PCI hotplug) | yes (CPU/mem/device hotplug) | n/a | via VMM | n/a (it's a process) | typically none |
| Live migration | no (snapshot/restore instead) | yes (mature) | yes | no (checkpoint/restore exists) | via VMM | checkpoint/restore (CRIU) | rarely |
| Snapshot/restore | yes (full + diff; UFFD lazy load) | yes (savevm) | yes | yes (checkpoint) | via VMM | CRIU | varies |
| Attack surface | very small (minimal devices + Rust + jailer + seccomp) | large (huge C device model) | moderate (smaller than QEMU, Rust) | moderate-novel (the Sentry is the kernel surface) | VM boundary + container surface | largest for hostile guests (shared kernel) | small (tiny TCB, but immature tooling) |
| Primary use case | serverless, multi-tenant, high density | general-purpose virtualization | modern cloud guests (full-featured VMs) | sandboxing semi-trusted containers | VM-grade isolation for OCI/K8s workloads | cooperative / single-tenant containers | single-purpose appliances |
Where each one actually fits
QEMU — the everything machine
QEMU is the reference against which Firecracker defines itself. It emulates a complete PC: BIOS/UEFI firmware, PCI and USB buses, SCSI, GPUs, sound, dozens of NIC models, and many guest architectures via TCG when there's no KVM. That generality is exactly why people reach for it — it boots almost any OS, including legacy and Windows guests, supports device passthrough and mature live migration, and has two decades of tooling.
Why Firecracker doesn't "just use QEMU": the generality is the cost. Hundreds of emulated devices in C are hundreds of thousands of lines of privileged host code that a hostile guest can attack; firmware and PCI probing add hundreds of milliseconds and tens of MiB before the kernel even starts; and you cannot densely pack thousands of mutually-untrusting tenants per host when each one drags a full machine behind it. For a serverless platform booting short-lived, multi-tenant functions, "QEMU has it" is not an argument — it's a description of the surface area Firecracker deliberately refuses. This is the heart of the minimal-device-model philosophy; internalize it, because it's the maintainers' default answer to feature-creep PRs (maintainer-mindset.md).
Cloud Hypervisor — the close cousin
Cloud Hypervisor is the most important comparison for a Firecracker contributor, because it is the
other VMM built on rust-vmm — it shares the same low-level crates (kvm-ioctls, vm-memory,
linux-loader, …) Firecracker uses (rust-vmm index). Both are Rust, both ride
KVM, both reject QEMU's C device sprawl. The difference is target: Cloud Hypervisor aims at modern,
full-featured cloud guests — virtio-PCI, ACPI, CPU/memory/device hotplug, VFIO passthrough, live
migration. It is "a clean, modern, secure VMM for general cloud workloads."
Firecracker, by contrast, optimizes ruthlessly for density and minimal surface at the cost of those features. The clean way to hold the two: Cloud Hypervisor is what you build when you want a better QEMU; Firecracker is what you build when you want the smallest possible VM that still boots Linux and does I/O. They are siblings sharing a substrate, not competitors — and contributions to the shared rust-vmm crates benefit both (what-is-rust-vmm.md).
gVisor — a different boundary entirely
gVisor is not the same kind of thing. There is no hardware-virtualization boundary by default; instead a userspace process (the Sentry) implements a Linux-compatible kernel and intercepts the container's syscalls, servicing them itself rather than letting them hit the host kernel. The isolation comes from never giving the workload a real host syscall surface, not from VT-x.
The trade-offs are inverted relative to Firecracker: no VM to boot (so container-class startup), but a large, novel trusted surface — the Sentry re-implements a lot of kernel behavior in Go, and compatibility and the Sentry's own correctness become the security story. It shines for sandboxing semi-trusted containers where you want stronger-than-namespaces isolation without paying for a VM. Firecracker's bet is the opposite: pay for a real (but minimal) VM, and lean on the hardware boundary plus a tiny VMM rather than a large software kernel.
Kata Containers — the integrator, not a competitor
Kata is frequently miscompared to Firecracker; it's actually a consumer of VMMs. Kata runs each OCI container (or pod) inside its own lightweight VM, giving Kubernetes/containerd workloads VM-grade isolation while keeping the container UX. Crucially, Kata can use Firecracker (or Cloud Hypervisor, or QEMU) as its underlying VMM. So "Firecracker vs Kata" is a category error: Kata is the orchestration/runtime layer; Firecracker is one of the engines it can sit on top of. The Firecracker analogue at this layer is firecracker-containerd, which similarly runs OCI containers inside Firecracker microVMs.
runc / containers — the baseline
runc (the OCI runtime under Docker/containerd) is the floor: namespaces + cgroups + seccomp, sharing the host kernel. Fastest startup, lowest overhead, simplest — and the weakest boundary against a hostile guest, because a kernel exploit is a host compromise; there is no second wall. This is precisely the gap Firecracker exists to fill: container-grade density and speed with VM-grade isolation. The whole reason AWS built Firecracker is that for multi-tenant Lambda/Fargate, shared- kernel containers were not a strong enough boundary, and full VMs were too heavy. See the "why Firecracker exists" framing.
Unikernels — the other minimalism
Unikernels chase the same "minimal footprint" goal from the opposite direction: instead of a minimal VMM running a general-purpose kernel, link the application directly with library-OS components into a single bootable image with no general-purpose OS, no shell, no multiple processes. Tiny TCB, fast boot, small image. The cost is the ecosystem: you generally rebuild your app against the unikernel toolchain, debugging and operational tooling are immature, and the model fits single-purpose appliances far better than arbitrary workloads. Firecracker keeps a normal, unmodified Linux guest (any rootfs, any binaries) and puts the minimalism in the VMM, not the guest — which is why it can run unmodified Lambda/Fargate workloads where a unikernel would require porting.
The trade-off in one mental model
stronger isolation vs hostile guest ◄──────────────────────────────► weaker
full VM microVM userspace-kernel shared-kernel
(QEMU, (Firecracker, (gVisor) (runc)
Cloud Hyp.) Kata-on-FC)
heavier (boot/mem/surface) ◄──────────────────────────────► lighter
QEMU Cloud Hyp. Firecracker / gVisor runc
Firecracker deliberately sits at the corner almost nothing else occupies: the isolation strength of a VM, near the footprint of a container. It buys that corner by refusing device surface area — which is why, as a contributor, the bar for adding surface is so high. Every device, every API field, every transport is host code that erodes the very property in the bottom-right of the first diagram. When you propose a feature, ask which corner it moves Firecracker toward; if the answer is "toward QEMU," expect resistance, and have a density-or-isolation reason ready.
Note — who runs on Firecracker. The bet has paid off in adoption: AWS Lambda and Fargate, Fly.io, firecracker-containerd, Kata, Vercel Sandbox, Northflank, Koyeb, Qovery, flintlock, and others run multi-tenant or untrusted workloads on it precisely because of the minimal-surface + hardware-boundary combination. That production pressure is why the maintainers guard the surface so hard — it is infrastructure, not a demo.
Quick decision guide
| If you need… | Reach for… |
|---|---|
| Densely packed, short-lived, multi-tenant workloads with VM isolation | Firecracker |
| A full-featured modern cloud guest (PCI, ACPI, hotplug, migration), still Rust/minimal-ish | Cloud Hypervisor |
| To boot anything (Windows, legacy OSes, exotic devices, passthrough) | QEMU |
| Stronger-than-namespaces sandboxing for semi-trusted containers, no VM boot | gVisor |
| VM-grade isolation for OCI/K8s workloads with container UX | Kata (on Firecracker / Cloud Hypervisor / QEMU) |
| Fastest, lightest containers for cooperative / single-tenant code | runc |
| A single-purpose appliance with the tiniest possible TCB, willing to rebuild the app | Unikernel |
Related references
- Introduction — why Firecracker exists and the same comparison in narrative form.
- Minimal-device-model philosophy — the contributor-facing version of "why so little machine."
- Maintainer mindset — how the attack-surface argument shows up in PR review.
- rust-vmm: what is it — the shared substrate beneath Firecracker and Cloud Hypervisor.
- Glossary — Cloud Hypervisor, gVisor, Kata, unikernel, runc defined in one line each.
Next: return to the Appendix index to pick your next reference, or back to the Introduction to re-read the project's thesis now that you can place it precisely in the landscape.