Firecracker vs Xen: two generations of the same idea
For most of the time that "the cloud" has existed as a thing you could put on a credit card, it ran on Xen. EC2 launched in 2006 on a Xen-based hypervisor and stayed there for over a decade, which means that an entire generation of engineers learned what virtualization is by learning what Xen does: a hypervisor underneath everything, a privileged control domain that owns the hardware, guests that are domains rather than processes, paravirtualized drivers, live migration as the answer to host maintenance. If your mental model of "a VM" includes the phrase "the hypervisor schedules it," that model came from Xen, whether or not you ever typed `xl`.
I'm Ajay; I built PandaStack. Firecracker came out of the same company as EC2 — specifically out of the Lambda and Fargate side of it, where the workload is not "a customer's long-lived server" but "a few hundred milliseconds of somebody's code, ten thousand times a second" — and it gave a deliberately different answer. This post is a careful head-to-head: how Xen is actually put together versus how Firecracker is, what's really in each boot path, per-guest footprint and density, the device-model attack surface argument (which is Firecracker's central claim, and a fair one), what "small trusted computing base" honestly means for each once you stop sloganeering, why live migration and snapshot/fork are not competing features but different problems, and where each of these genuinely wins. Then what the Firecracker shape buys in practice, with the numbers I can actually stand behind.
Two origin stories, twenty years apart
Xen came out of the University of Cambridge Computer Laboratory in the early 2000s, at a moment when x86 hardware had no virtualization extensions at all. That constraint shaped everything. You could not simply trap and emulate privileged instructions on x86 the way the theory said you should, because x86 had instructions that behaved differently in ring 0 and ring 3 without faulting. Xen's answer was paravirtualization: modify the guest kernel so it knows it is virtualized and asks the hypervisor politely, via hypercalls, instead of executing privileged instructions and hoping. That was a radical, pragmatic trade — you gave up running unmodified operating systems in exchange for performance that was actually usable on the hardware of the day. It worked well enough that Amazon built a public cloud on it.
Firecracker was open-sourced by AWS in 2018, having grown out of Google's crosvm, and the constraints were entirely different. Hardware virtualization extensions had been standard for a decade. KVM had turned the Linux kernel itself into a competent hypervisor. The problem was no longer "can we virtualize x86 at acceptable speed" — it was "we are running millions of tiny, untrusted, short-lived functions per second and the per-guest cost of a general-purpose VM is ruinous, in both boot latency and memory." So Firecracker's design question was not how to virtualize, but how much machine you can refuse to provide and still have something that runs Linux. It's worth noting what happened to EC2 in between, because it's the honest bridge between the two stories: AWS moved newer instance families onto the Nitro system, which pairs a lightweight KVM-based hypervisor with dedicated hardware that takes over networking, storage, and management. The direction of travel is the same in both cases — shrink the thing running on the host CPU next to the guest. Xen put a great deal of machinery there because in 2003 there was nowhere else to put it.
How Xen is actually put together
Xen is a type-1 hypervisor in the strict sense: it boots before any operating system does. The bootloader loads Xen, Xen initializes the machine, and only then does Xen start the first domain. There is no host OS underneath it — Xen is the thing closest to the metal, and Linux, if present, runs on top of it as a guest with special privileges.
dom0, domUs, and where the drivers live
That first domain is dom0: a privileged control domain, in practice a full Linux (or NetBSD) kernel, which is granted access to the physical hardware and runs the device drivers. Everything else is a domU — an unprivileged guest. This split is the single most important structural fact about Xen. The hypervisor itself deliberately does not contain a driver for your NIC, your NVMe controller, or your RAID card. It contains CPU scheduling, memory management, interrupt routing, and the mechanisms domains use to talk to each other. All the messy hardware-specific code lives in dom0, in a Linux kernel, one privilege level up from the guests.
Guests reach the outside world through split drivers: a frontend driver in the guest (netfront, blkfront) talking to a backend driver in dom0 (netback, blkback) over shared memory rings set up with grant tables, with notifications delivered as event channels, and device discovery mediated by xenstore over xenbus. This is a genuinely elegant design and it predates virtio by years — virtio is, in a real sense, the same idea generalized after Xen proved it worked. If you have ever wondered why a Xen guest sees `/dev/xvda` and a console called `hvc0`, that's why: those are paravirtual devices, not emulated ones.
PV, HVM, and PVH: three different guests wearing the same hypervisor
Xen guests come in modes, and conflating them is where most "Xen is slow / Xen is insecure" arguments go wrong. Classic PV is the original: no hardware virtualization used, the guest kernel is modified and makes hypercalls, no emulated chipset at all. HVM uses hardware virtualization extensions so an unmodified guest OS (including Windows) can boot, which means the guest expects a real-looking machine — firmware, a PCI bus, an IDE controller, a VGA adapter — and Xen provides that by running a QEMU device model process, historically in dom0, optionally in an isolated stubdomain. PVH is the modern synthesis: hardware virtualization for CPU and memory, paravirtual devices for I/O, and no emulated legacy chipset and no QEMU device model at all.
PVH matters for this comparison beyond Xen itself, because the PVH boot entry point — a way to start a kernel directly with no firmware and no bootloader — came out of the Xen world, and Firecracker can use it too. I wrote up that entry path in /blog/firecracker-pvh-boot-protocol-explained. The industry converged: the fast, minimal way to start a Linux guest was invented on the Xen side, and the minimal-VMM crowd adopted it.
# Xen: you do not configure a running process. You describe a DOMAIN to the
# toolstack in dom0, and dom0 asks the hypervisor -- which booted before Linux
# did -- to build it for you.
cat > /etc/xen/guest1.cfg <<'EOF'
type = "pvh" # "pv" = classic paravirt, no hardware assist
# "hvm" = hardware assist PLUS a QEMU device model process
# "pvh" = hardware assist, PV devices, no emulated chipset
name = "guest1"
kernel = "/srv/guest1/vmlinuz"
extra = "console=hvc0 root=/dev/xvda1"
vcpus = 2
memory = 1024 # MB target; maxmem lets you balloon the domain up later
# Split drivers. xvda is a FRONTEND in the guest talking to a BACKEND that
# lives in dom0 -- or, if you have done the work, in a dedicated driver domain
# whose compromise does not hand an attacker the control domain.
disk = [ "/srv/guest1/root.img,raw,xvda,rw" ]
vif = [ "bridge=xenbr0" ]
EOF
xl create /etc/xen/guest1.cfg # dom0 asks the hypervisor to build it
xl list # domains, not processes
xl save guest1 /var/lib/xen/guest1.save # suspend the domain to a state file
xl migrate guest1 host2 # the move Firecracker cannot makeHow Firecracker is put together
Firecracker inverts the layering. There is no hypervisor underneath Linux; Linux is the hypervisor, via KVM, and Firecracker is an ordinary userspace process that asks the kernel to create a VM and run vCPUs on its behalf. People argue about whether that makes it "type 2," and the argument is not very useful — the practically important fact is that the privileged virtualization code lives inside the host kernel you were already running, and the VMM is a process you can jail, count, and kill. If you want the mechanics of that interface, I covered it in /blog/kvm-explained-for-developers.
One microVM is one Firecracker process. Inside it, the device model is deliberately anaemic:
- A handful of virtio devices and nothing else — net, block, vsock, balloon, and an entropy source, plus a serial console and a minimal keyboard controller that exists mostly so the guest can trigger a reset.
- No BIOS and no UEFI — Firecracker loads a kernel image directly and jumps into it, via the Linux 64-bit boot protocol or the PVH entry point. There is no firmware phase to sit through and no firmware to exploit.
- No PCI bus on x86 — virtio rides MMIO transport instead, so the guest never runs a bus enumeration pass and there is no PCI configuration space for a hostile guest to poke at. The tradeoff and its consequences are in /blog/firecracker-mmio-vs-pci-transport-explained.
- No hardware passthrough — no VFIO, no GPU, no real NIC handed to a guest. This is not a missing feature list, it is the product.
- Seccomp-filtered by default — the VMM process runs behind a syscall allowlist, so even a fully compromised VMM is talking to a deliberately narrow slice of the host kernel. Details in /blog/firecracker-seccomp-bpf-filter-explained.
- Confined by the jailer — a separate binary that sets up a chroot, cgroups, namespaces, and a dropped-privilege context before exec'ing the VMM, which is the thing that makes "one process per guest" an actual isolation story rather than a diagram. See /blog/firecracker-jailer-explained.
The configuration interface reflects the same minimalism. You don't declare a machine topology, because there barely is one.
# Firecracker is a userspace process. It is ALREADY running -- launched by the
# jailer inside a chroot, a cgroup, and its own namespaces -- and you configure
# the machine by PUTting JSON at its Unix socket. Nothing booted before Linux.
API=/srv/vm1/firecracker.sock
# 1. Boot source: a raw kernel image and a command line. No BIOS, no UEFI, no
# bootloader, no domain builder. Xen's toolstack does the equivalent inside
# dom0 -- libxl asks the hypervisor to build a domain and lays the kernel
# out in its memory. Here, the VMM opens a file.
curl --unix-socket $API -X PUT http://localhost/boot-source \
-H 'Content-Type: application/json' \
-d '{"kernel_image_path": "/srv/vm1/vmlinux",
"boot_args": "console=ttyS0 reboot=k panic=1 pci=off"}'
# 2. Root drive. path_on_host is a file THIS process opens with an ordinary
# open(2). Xen's split drivers put blkfront in the guest and blkback in
# dom0, talking over a grant-table ring: the data path crosses a DOMAIN
# boundary, not merely a process boundary.
curl --unix-socket $API -X PUT http://localhost/drives/rootfs \
-H 'Content-Type: application/json' \
-d '{"drive_id": "rootfs", "path_on_host": "/srv/vm1/rootfs.ext4",
"is_root_device": true, "is_read_only": false}'
# 3. Network: one tap device in the network namespace the VMM was launched
# into. Xen's equivalent is a vif whose netback half lives in dom0 and is
# wired into a bridge by hotplug scripts the toolstack runs for you.
curl --unix-socket $API -X PUT http://localhost/network-interfaces/eth0 \
-H 'Content-Type: application/json' \
-d '{"iface_id": "eth0", "host_dev_name": "tap0"}'
# 4. Size it, start it. Note pci=off above: on x86 there is no PCI bus to
# enumerate, so that whole boot phase simply does not happen. An HVM domU
# under Xen boots firmware and walks an emulated PCI bus presented by a
# QEMU device model process running outside it.
curl --unix-socket $API -X PUT http://localhost/machine-config \
-H 'Content-Type: application/json' \
-d '{"vcpu_count": 2, "mem_size_mib": 1024}'
curl --unix-socket $API -X PUT http://localhost/actions \
-H 'Content-Type: application/json' \
-d '{"action_type": "InstanceStart"}'Put the two blocks side by side and the philosophical difference is visible in one screen. Xen's config describes a machine and its wiring, because a domain is a durable thing with an identity that outlives any single process and can be moved between hosts. Firecracker's config is four PUTs and a start action, because a microVM is a process with a kernel inside it, and the plan for when something goes wrong is to kill it and make another one.
What's actually in the boot path
Boot time comparisons get quoted carelessly, so let's talk about phases rather than milliseconds. An HVM guest under Xen has the longest path: the toolstack builds the domain, a QEMU device model process starts and presents a machine, firmware runs, firmware enumerates a PCI bus and initializes emulated devices, a bootloader loads, and then finally the guest kernel starts and discovers it should switch over to PV drivers. Every one of those phases exists for a good reason — it is what lets an unmodified operating system boot — and every one of them is time you spend before your code runs.
A PVH domU skips most of that: no firmware, no emulated chipset, no device model process, straight into the kernel. That is Xen's fast path and it is genuinely fast. Firecracker's cold path is structurally similar — direct kernel load, no firmware, no bus enumeration, a couple of MMIO virtio devices — and then it does something Xen's design was never aiming at, which is to skip booting altogether. I go through the mechanics in /blog/firecracker-memory-snapshots, but the shape is: boot a guest once, capture its memory and its (very small) device state, and thereafter start new guests by restoring that image and resuming, rather than by booting anything at all.
This is the point where the two designs stop being comparable on a single axis. Xen's fast path is "boot a domain quickly." Firecracker's fast path is "do not boot." The reason the tiny device model matters so much here is not only security: a machine with five virtio devices has almost no device state to serialize, so the snapshot is essentially just guest RAM, and restore is dominated by how fast you can get pages in front of the guest.
Footprint and density
Per-guest overhead is the other axis where the era shows. A Xen HVM domain costs you the domain's memory plus a QEMU device model process per guest, and that device model is a general-purpose machine emulator with a working set to match. PVH removes that process entirely, which is a large part of why PVH exists. On the Firecracker side, each guest is one process with a small fixed VMM overhead on top of the guest's RAM allocation, and no auxiliary per-guest processes at all.
I'm deliberately not going to hand you a table of megabytes, because the honest answer depends on guest configuration, kernel, and host in ways that make any single number misleading — measure the configuration you intend to ship. What I will say is the structural point: when a guest lives for three weeks, a few tens of megabytes of per-guest overhead is a rounding error against the workload. When a guest lives for four hundred milliseconds and you are trying to run thousands of them per host per minute, per-guest overhead is the business model. Xen was built for the first case. Firecracker was built for the second.
The device-model argument, stated fairly
Here is Firecracker's central design claim, and it deserves to be stated properly rather than as a marketing line. In any VM, the code a hostile guest can actually reach is the device emulation code — the thing that parses the guest's reads and writes to virtual hardware. That code is, definitionally, a parser of attacker-controlled input running outside the guest's isolation boundary. So the security question is not "is this a hypervisor" but "how much attacker-reachable code sits on that boundary, and what language is it written in."
For a Xen HVM guest, that surface includes a full QEMU device model: an emulated chipset, PCI, IDE/SATA, USB, VGA, and the rest, in C, because that is what it takes to make an unmodified OS believe it is on real hardware. Xen has taken this seriously for a long time and offers real mitigations — run the device model in a stubdomain rather than dom0, use driver domains so a compromised backend does not equal a compromised control domain, or use PVH and have no device model at all. Those are good answers. They are also answers most deployments do not implement, and "the secure configuration exists" is not the same as "the deployed configuration is secure."
For Firecracker, the reachable surface is roughly five virtio devices and a serial port, written in Rust, behind a seccomp allowlist, in a jailed process. That is a much smaller number of lines of much safer code. This claim is fair, and it is the single strongest thing you can say about Firecracker's design. It is also not the whole story, which brings us to the part everybody oversells.
What "small TCB" honestly means for each
Both communities have a favourite slogan, and neither one survives contact with the actual boundary. The Firecracker slogan is "the VMM is only about fifty thousand lines of Rust." True, and a real achievement. But the VMM is not the whole trusted computing base, because the thing enforcing the virtualization boundary is KVM, and KVM lives inside the Linux kernel — the same kernel that also contains every filesystem, network stack, and driver on the host. A guest escaping into the Firecracker process still faces seccomp and the jailer, which is exactly why those exist; but the isolation ultimately rests on the correctness of KVM and of the host kernel surface reachable through it. "Small VMM" is accurate. "Small TCB" is a stretch, because Linux is in there.
The Xen slogan is "the hypervisor is far smaller than Linux." Also true — Xen's hypervisor is on the order of hundreds of thousands of lines, against a Linux kernel measured in tens of millions, and it deliberately excludes device drivers. But dom0 is a full Linux kernel with all those drivers, holding privilege over every guest on the box, and in the default HVM configuration a QEMU device model sits on the guest-facing boundary. So the hypervisor is small and the control plane above it is not. Xen's genuine architectural advantage here is that it gives you the tools to disaggregate — stubdomains, driver domains, dom0 disaggregation — and if you actually use them, you get a decomposition that a KVM host does not naturally offer. That is a real and underrated property, and it is why Xen remains the substrate for security-focused systems that care intensely about this decomposition.
Live migration vs snapshot and fork: different problems
Xen has mature live migration, and it has had it for a very long time. You can move a running domain from one host to another, iteratively copying dirty pages until the remaining set is small enough to pause, transfer, and resume, with the guest's TCP connections intact and nobody inside the guest any the wiser. This is not a nice-to-have; it is the feature that makes it possible to patch a hypervisor, retire a machine, or rebalance a rack without telling ten thousand customers to schedule downtime. If your guests are long-lived servers, live migration is close to the whole operational story.
Firecracker does not do this, and I want to be honest rather than clever about it: there is no live migration. What it has instead is snapshot and restore — freeze a guest to a memory file plus a small state file, and start new guests from that image. Those are not the same feature and they do not substitute for one another. Live migration answers "this host needs to go away and the guest must not notice." Snapshot/restore answers "I need another one of these, right now, and I need it before the user's request times out."
Live migration exists because losing the guest is unacceptable. Snapshot-restore exists because losing the guest is routine, and creating a replacement is nearly free.
Snapshot-restore then unlocks something migration never aimed at: fork. Restore the same memory image twice and you have two guests that share a common past — same booted kernel, same warm page cache, same loaded interpreter — diverging from the moment they resume. Backed by copy-on-write memory and a reflinked or dm-snapshot root disk, that turns "give me twenty variants of this environment" into a cheap operation rather than twenty boots. I unpack the distinctions between fork, clone, and snapshot in /blog/microvm-fork-vs-clone-vs-snapshot-explained. Xen can save and restore a domain too, but the design was never optimizing for restore-as-the-normal-create-path, so the whole machine around it — device state size, toolstack overhead, domain build cost — was never squeezed for that case.
Side by side
- Layering — Xen (HVM and PV-PVH alike): a type-1 hypervisor that boots before any OS, with a privileged dom0 Linux owning the drivers. Firecracker: a userspace process on a normal Linux host, using KVM, so Linux itself is the hypervisor and the VMM is something you can jail, cgroup, and kill.
- Guest-facing device surface — Xen HVM: a full QEMU device model (chipset, PCI, IDE, USB, VGA) in C, optionally isolated in a stubdomain. Xen PVH: paravirtual devices only, no device model process at all. Firecracker: about five virtio devices plus a serial port, in Rust, behind seccomp and the jailer.
- Boot path — Xen HVM: domain build, device model, firmware, PCI enumeration, bootloader, then the kernel. Xen PVH: domain build straight into the kernel, no firmware. Firecracker: direct kernel load with no firmware and no PCI, and in production usually no boot at all because you restore a snapshot instead.
- Guest OS breadth — Xen HVM: unmodified operating systems including Windows and the BSDs, with wide device support. Xen PV-PVH: Xen-aware kernels. Firecracker: minimal Linux-family guests it boots directly; no unmodified Windows, no legacy hardware, no passthrough.
- Hardware access — Xen: PCI passthrough, driver domains, a genuine general-purpose IaaS hardware story. Firecracker: none — no VFIO, no GPU, no physical NIC in a guest. This is a deliberate omission, and it is disqualifying for some workloads.
- Moving a running guest — Xen: mature live migration, the reason you can patch a host without customer downtime. Firecracker: no live migration; snapshot and restore instead, which solves a different problem and solves it very well.
- Per-guest overhead at scale — Xen HVM: guest RAM plus a device model process per guest, which is fine for tens of long-lived VMs and expensive for thousands of short-lived ones. Xen PVH: materially lighter, no device model. Firecracker: one process with small fixed VMM overhead, designed from the start for density of disposable guests.
- Operational ecosystem — Xen: decades of tooling (xl/libxl, XCP-ng, Xen Orchestra), an established IaaS and security-appliance ecosystem, and an installed base that predates most of your dependencies. Firecracker: a library-grade VMM with no built-in orchestration, which means you either build a control plane or adopt one — a choice I sized up in /blog/build-vs-buy-firecracker-sandbox.
- The workload it was designed for — Xen: long-lived, general-purpose, multi-tenant IaaS guests that must survive host maintenance. Firecracker: short-lived, high-churn, dense, untrusted guests where create latency and per-guest overhead are the entire cost structure.
Where each genuinely wins
Reach for Xen when
You are running general-purpose multi-tenant IaaS: customers' own operating systems, arbitrary kernels, Windows guests, wide device support, guests that run for months. You need live migration, because host maintenance cannot mean customer downtime. You want a hypervisor that is architecturally independent of Linux — the fact that dom0 is Linux is a deployment choice, not a structural requirement, and there are systems that care about that distinction very much. You want real privilege decomposition: driver domains that confine a compromised NIC backend, stubdomains that confine a device model, a dom0 you can carve up. Or you have hardware to pass through — a GPU, a specialised NIC, a card with a vendor driver — which Firecracker simply cannot do. None of these are legacy requirements. They are the requirements of a different job.
Reach for Firecracker when
Your guests are small, short-lived, numerous, and running code you would not trust with a shell on a shared host. Serverless functions. Code interpreters. Per-request isolation for an LLM application. CI runners that must be pristine every time. AI agent sandboxes executing model-authored commands, which is the case where a container's shared kernel stops feeling like an implementation detail and starts feeling like a decision you'll have to explain. In those workloads, the general-purpose machinery Xen provides is pure cost: firmware you don't need, a device model you don't want on your attack surface, passthrough you'll never configure, and live migration for guests that will be dead in ninety seconds anyway. Refusing to provide hardware is the product.
What the Firecracker shape buys in practice
PandaStack is built on the second half of that split, so I can be concrete about what the architecture actually delivers. Every sandbox, managed database, and hosted app is its own Firecracker microVM. There is no warm pool of idle guests waiting around: every create restores a baked snapshot on demand. The restore step itself runs about 49ms, and end to end — network slot, disk clone, process spawn, restore, resume, readiness probe — a create lands at roughly 179ms p50 and about 203ms p99. The ~3s cold boot happens once, when the template is baked, and then never again in the request path.
Around that sit the properties that only make sense once boot is a restore. Same-host fork is 400–750ms and cross-host 1.2–3.5s, because a fork is a memory image plus a copy-on-write root disk rather than a second boot. Guest memory can be streamed on demand from object storage through userfaultfd, so a host does not need to download a multi-gigabyte memory file before it can start a guest — pages arrive as the guest touches them. The root filesystem is copy-on-write via reflink or dm-snapshot, so cloning a disk is a metadata operation. Networking is pre-allocated rather than built per guest: each agent holds 16,384 ready-made /30 subnets, each with its own network namespace and TAP device, because the ~100ms of `ip netns` and `iptables` work you'd otherwise do per create would dominate a 179ms budget.
Read that list back against Xen's design goals and the divergence is total. None of it is something Xen was ever trying to give you, and none of it would have been a sensible thing to optimize for in 2003, when a guest was a server you named after a Greek god and expected to still be running in a year.
from pandastack import Sandbox
import json
# What a guest costs when "boot" is a restore rather than a boot.
#
# There is no domain to build, no firmware phase, no PCI bus to enumerate and
# no kernel to start: the VMM process spawns, maps a snapshot of an ALREADY
# BOOTED guest, and resumes it. ~49ms of the wall clock below is that restore
# step; ~179ms p50 is the whole create, readiness probe included.
#
# The consequence is a different unit of isolation. You stop asking "can I
# afford a VM for this?" and start asking "why would I share one?"
def analyze(job_id: str, tenant_id: str, payload: bytes) -> dict:
sbx = Sandbox.create(
template="code-interpreter",
ttl_seconds=900, # a wedged job is reaped, not babysat
metadata={"job": job_id, "tenant": tenant_id},
)
try:
sbx.filesystem.write("/work/input.json", payload)
out = sbx.exec(
"cd /work && python3 -m analyze --input input.json --out out.json",
timeout_seconds=600,
)
if out.exit_code != 0:
# No cleanup logic to get right, no state to unwind. The blast
# radius of a failure is one machine that was going to die anyway.
raise AnalysisFailed(job_id, out.exit_code, out.stderr[-4000:])
return json.loads(sbx.filesystem.read("/work/out.json"))
finally:
# A Xen domain is something you migrate to keep alive. This is not
# that kind of guest. It is a process with a kernel in it, and the
# correct end of its life is now.
sbx.kill()The summary
Xen and Firecracker are the same idea — put a hardware-enforced boundary around untrusted code — separated by twenty years of hardware and one enormous change in what a guest is for. Xen was designed when x86 could not virtualize itself, when a guest was a long-lived server, and when the only place to put device drivers was a privileged Linux domain sitting next to the hypervisor. Everything about it follows from that: paravirtualized split drivers, the dom0/domU divide, a toolstack that describes machines, and live migration as the answer to the question "what happens when this host has to go away."
Firecracker was designed when hardware virtualization was free, KVM was already in the kernel you were running, and the guest had become a disposable unit of work measured in hundreds of milliseconds. So it deletes everything the new workload doesn't need — firmware, PCI, USB, a general-purpose device model, passthrough, migration — and spends the savings on being small enough to audit, cheap enough to run thousands of, and simple enough to snapshot and restore instead of booting. The device-model argument is real and Firecracker wins it. The "tiny TCB" argument is softer than either camp admits, because KVM is Linux and dom0 is Linux, and the only honest version of the question is which code a hostile guest can reach in your specific configuration.
If you're choosing, don't choose on architecture aesthetics. Choose on guest lifetime and guest count. Long-lived, general-purpose, hardware-hungry guests that must survive host maintenance: that is Xen's job and it has been doing it well since before your framework existed. Short-lived, numerous, untrusted guests where create latency is a user-visible number: that's what Firecracker was built for, and the whole design — down to refusing to give the guest a PCI bus — makes sense once you accept that the correct end of a guest's life is usually about ninety seconds after it began.
For the adjacent comparisons: the general-purpose VMM version of this argument is in /blog/firecracker-vs-qemu, the other minimal-VMM-on-KVM contender is covered in /blog/firecracker-vs-cloud-hypervisor, and the comparison most people actually need before either of these — a shared kernel versus a real one — is in /blog/firecracker-vs-docker.
Frequently asked questions
Is Firecracker a type-1 or type-2 hypervisor compared to Xen?
Xen is unambiguously type-1: it boots before any operating system, initializes the machine itself, and then starts a privileged control domain (dom0) that owns the device drivers. Firecracker is a userspace process running on an ordinary Linux host, using KVM, so it is usually described as type-2 — though the label is unhelpful because KVM turns the Linux kernel itself into a hypervisor, giving the guest hardware-enforced isolation just as Xen does. The practically useful distinction is not the label but the layering. Under Xen, the privileged virtualization code is a separate, smaller codebase beneath Linux, and Linux runs as a privileged guest on top of it. Under Firecracker, the privileged virtualization code is inside the host kernel you were already running, and the VMM is a process you can seccomp-filter, jail, cgroup, and kill like any other.
Why did AWS build Firecracker when EC2 already ran on Xen?
Because Lambda and Fargate have a different workload than EC2 instances. An EC2 instance is a long-lived, general-purpose virtual server that must support unmodified operating systems, wide device compatibility, and host maintenance without customer downtime — which is exactly what Xen was designed for. A Lambda invocation is a few hundred milliseconds of untrusted code, executed enormously often, where the dominant costs are create latency and per-guest memory overhead. A general-purpose VM's firmware phase, PCI enumeration, and full device model are pure overhead for that shape, and its per-guest footprint sets a hard ceiling on density. Firecracker strips the machine down to a handful of virtio devices with no firmware and no PCI bus, in memory-safe Rust behind seccomp and a jailer, so that a guest becomes cheap enough to create per unit of work rather than per customer.
Does Firecracker support live migration like Xen does?
No. Firecracker has no live migration, and it is worth being direct about that rather than presenting snapshots as an equivalent. Xen has mature live migration: it iteratively copies a running domain's dirty memory pages to another host, then briefly pauses, transfers the remainder, and resumes there, with the guest's connections and state intact. That is what lets an operator patch a hypervisor or retire a machine without customer downtime, and if your guests are long-lived servers it is close to the entire operational story. What Firecracker offers instead is snapshot and restore: freeze a guest to a memory file plus a small device-state file, and create new guests by restoring that image rather than booting. These solve different problems. Migration exists because losing a guest is unacceptable; snapshot-restore exists because losing a guest is routine and replacing it is nearly free — which in turn makes copy-on-write forking practical.
Is Firecracker's trusted computing base really smaller than Xen's?
The honest answer is that both common slogans are oversold. Firecracker's VMM is roughly fifty thousand lines of Rust, which is genuinely small and genuinely safer than a large C device model — but the code enforcing the virtualization boundary is KVM, which lives inside the Linux kernel, so the host kernel is in your trusted computing base. Xen's hypervisor is far smaller than Linux, on the order of hundreds of thousands of lines, and deliberately contains no device drivers — but dom0 is a full Linux kernel holding privilege over every guest, and in the default HVM configuration a QEMU device model sits directly on the guest-facing boundary. Xen's real advantage is that its architecture lets you disaggregate that privilege using driver domains and stubdomains, which a KVM host does not naturally offer. The question worth answering is not which project has fewer lines, but what code a hostile guest can reach in the configuration you actually deploy.
When should I use Xen instead of Firecracker?
Use Xen when you are running general-purpose, long-lived guests: customers' own operating systems including unmodified Windows and the BSDs, arbitrary kernels, wide device support, and VMs expected to stay up for months. Use it when you need live migration, because host maintenance cannot mean downtime. Use it when you need hardware passthrough — a GPU, a specialised NIC, a card with a vendor driver — which Firecracker simply does not support, having no PCI bus or VFIO at all. Use it when you want privilege decomposition that a Linux host does not offer natively: driver domains that confine a compromised device backend, or stubdomains that confine a device model. And use it when you want a hypervisor whose architecture is independent of Linux. Firecracker is the better answer only for the narrower case it was built for: short-lived, numerous, untrusted Linux guests where create latency and per-guest overhead dominate everything else.
49ms p50 cold start. Fork, snapshot, and scale to zero.