all posts

Firecracker vs crosvm: two rust-vmm siblings, two different jobs

Ajay Kumar··9 min read

Firecracker and crosvm are close enough in lineage that it's tempting to read a feature table and conclude they're competitors. They're both written in Rust, both sit on KVM, and both are among the original contributors to rust-vmm — the shared crate ecosystem that most modern minimal VMMs now build on. If you only looked at the git blame in rust-vmm's core crates, you'd assume these two projects are basically the same idea shipped twice. They are not. crosvm exists to put a graphical, interactive Linux (or Android) environment inside a sandbox a human sits in front of — a Chromebook running Crostini, an Android phone running a protected VM. Firecracker exists to run thousands of headless, ephemeral, server-side guests per host behind a REST API, for a cloud provider that will never see any of them render a pixel. That's not a difference of polish. It's a difference of who the guest's user is.

I'm Ajay, and I build PandaStack, which runs Firecracker microVMs as a service for AI agents and code execution — so read the Firecracker sections knowing I have a stake in that answer looking good. crosvm isn't really a competitor to what I build, though, and that's sort of the point of this post: it's solving a different problem well, for Google's own stack, and most of what makes it interesting has nothing to do with server-side sandboxing at all.

crosvm is a fast-moving, internally-developed-at-Google project with a device model, feature set, and CLI surface that changes across its release cadence and across the ChromeOS/Android/gVisor contexts that embed it. I'm stating the durable architectural shape with confidence — device model breadth, control-surface style, embedding context — but anything narrower (exact flags, exact snapshot capabilities in a given build, exact GPU backend support) you should verify against crosvm's own documentation and source, not a blog post.

Two cousins out of rust-vmm, raised in different houses

rust-vmm started as an effort to stop every Rust-based VMM from reimplementing the same KVM plumbing, virtio device backends, and boot logic from scratch. Firecracker and crosvm were both there at the founding, and both still draw on shared crates for things like the virtio transport and low-level KVM bindings. That shared ancestry is real and worth naming — it's why the two projects can sound alike in a changelog. But rust-vmm was always meant to be a toolkit, not a product, and the two products built on top of it point in almost opposite directions. Firecracker took the toolkit and built a minimal, supervised, API-driven server component. crosvm took the same toolkit and built a rich, embeddable VMM for running a full-featured Linux userland that a person interacts with directly.

You can see the divergence most clearly in who each project answers to. Firecracker's steering is oriented around AWS's own Lambda and Fargate needs and the broader cloud-sandboxing community that adopted it afterward. crosvm's steering is oriented around ChromeOS and Android product requirements — it has to do whatever running a Linux desktop or an Android VM inside a consumer device requires, because that's the job it was hired for.

What crosvm actually is

crosvm's origin story is ChromeOS's Crostini feature: the ability to run a real Linux environment, with real Linux apps, inside a sandboxed VM on a Chromebook. That's a demanding brief on the device-model side. The guest isn't a stateless worker process reading from stdin — it's a Linux desktop a person is looking at, clicking on, and expecting to feel native. So crosvm grew virtio-gpu support with GPU passthrough/acceleration so guest applications can actually render, virtio-wayland so guest windows composite onto the host's display server, audio devices so guest apps can make sound, and a general set of desktop-and-mobile-oriented virtio devices that a headless server VMM has no reason to carry.

The same VMM, or close variants of it, does more than Crostini today. It's used inside Android's Virtualization Framework (AVF) to run protected VMs — pVMs — as an isolation primitive on Android devices, which is a third embedding context with its own device and security requirements again. And gVisor, the syscall-interception sandbox, can use a crosvm-style KVM backend (its `--platform=kvm` option) as an additional hardware-isolation layer underneath its usual ptrace/systrap interception — meaning crosvm's job there is to be one layer in someone else's defense-in-depth stack, not the whole sandbox.

A device model sized for a human, not a headless worker

This is the detail that actually explains most of the rest of the comparison: more of these device types have to exist because the guest is often something a person is staring at. A shape-only illustration of what that looks like in practice — not real crosvm flags, just the idea of what a ChromeOS-style launch has to configure that a headless cloud sandbox never touches:

# =====================================================================
# ILLUSTRATIVE SHAPE ONLY. Not real crosvm CLI syntax -- crosvm's
# actual flags are version- and build-specific, and its real launch
# path is usually driven by ChromeOS's VM manager or Android's AVF,
# not typed by a human. Read crosvm's own docs/source before relying
# on any concrete syntax.
# =====================================================================

# Conceptually, what a Crostini-style launch has to describe:
#   - cpus / memory                  (same as any VMM)
#   - a rootfs image                 (same as any VMM)
#   - a GPU device, GPU backend      -> guest apps need to render
#   - a Wayland socket               -> guest windows composite onto
#                                       the host's display, live
#   - an audio device                -> guest apps play sound
#   - a shared filesystem            -> host <-> guest file exchange
#                                       for a user, not a data pipeline
#   - a network tap                  (same as any VMM)
#
# None of the GPU/Wayland/audio lines exist because a headless,
# server-side guest asked for them. They exist because the guest is
# a desktop a person is going to look at.

None of that is a criticism. A VMM whose guest renders windows for a human needs a GPU device and an audio device the same way a car needs headlights. The point is just that it's a structurally different device model from the one a headless sandbox platform needs, and every device you add to a guest's view of the world is one more thing a hostile or buggy guest can poke at.

What Firecracker actually is

Firecracker's brief was the opposite of Crostini's: run untrusted code from strangers, at Lambda and Fargate scale, where the guest never renders a frame and nobody is ever going to look at its screen. So the device model is deliberately starved down to what a headless server workload needs and nothing else — virtio-net, virtio-block, virtio-vsock, a serial console, an entropy source, and just enough of a keyboard controller to accept a reset signal. No GPU device exists to remove. There's no PCI bus, no BIOS, no bootloader, no graphics stack of any kind; the kernel is loaded directly and starts executing.

Around that minimal machine sits an operational shell built for orchestration rather than for a single embedding app: a REST API over a Unix domain socket that any language can drive, a jailer that chroots the VMM, drops it into its own namespaces and cgroups, and strips its privileges before it ever touches guest code, and a seccomp-BPF filter that narrows the VMM process to the small syscall set it actually needs. A rough shape of what actually happens when an orchestrator boots one, end to end:

# =====================================================================
# Firecracker: minimal headless machine, driven entirely over HTTP by
# whatever scheduler owns the fleet. No human ever looks at this VM.
# =====================================================================
set -euo pipefail
SOCK=/srv/jail/vm-7/root/run/firecracker.socket

# jailer forks+execs firecracker into a chroot with its own namespaces
# and cgroups, running as an unprivileged uid/gid, seccomp already on.
jailer --id vm-7 --exec-file /usr/bin/firecracker \
       --uid 10007 --gid 10007 --chroot-base-dir /srv/jail \
       --netns /var/run/netns/ns-vm-7 \
       -- --api-sock /run/firecracker.socket &

put() { curl -s --unix-socket "$SOCK" -X PUT "http://localhost$1" \
           -H 'Content-Type: application/json' -d "$2"; }

# Kernel loaded directly -- no firmware, no bootloader, no display.
put /boot-source '{"kernel_image_path":"./vmlinux",
  "boot_args":"console=ttyS0 reboot=k panic=1 pci=off"}'

put /machine-config '{"vcpu_count":2,"mem_size_mib":1024}'

# Root disk: a file, which is exactly what makes reflink clones and
# snapshot-restore cheap later.
put /drives/rootfs '{"drive_id":"rootfs","path_on_host":"./rootfs.ext4",
  "is_root_device":true,"is_read_only":false}'

# One NIC, no GPU device, no audio device, no Wayland socket -- there
# is nothing on the other end of this VM that would use them.
put /network-interfaces/eth0 '{"iface_id":"eth0","host_dev_name":"tap0"}'

put /actions '{"action_type":"InstanceStart"}'

# From here the scheduler owns this VM as a PID it can cgroup, signal,
# and reap -- the same shape whether it's guest #7 or guest #40,000.

The one thing crosvm can do that Firecracker structurally cannot: Firecracker is Linux-with-KVM, full stop. There's no macOS build, no Windows build, no path to one. crosvm's Google-scale reach across ChromeOS and Android has pushed it toward more platform and backend flexibility over time — exactly which backends it currently supports and how they're built is the kind of detail that shifts release to release, so check its docs rather than take a fixed list from anyone.

Side by side

Anything below that's build- or context-specific is flagged. Verify against current docs before designing anything around it.

  • What you get — Firecracker: a standalone VMM binary, exec'd and supervised by an orchestrator, with a REST API as its only control surface. crosvm: a VMM binary/library embedded into a larger platform's own VM manager — ChromeOS's Concierge, Android's AVF VirtualizationService, or gVisor's platform layer.
  • Control interface — Firecracker: a REST API over a Unix domain socket, meant for an arbitrary orchestrator in any language to drive fleets of guests. crosvm: a CLI and control-socket interface tied to its embedding context — it's driven by the platform that owns it, not by a general-purpose scheduler that expects to manage guests it didn't build the launcher for.
  • Host platforms / embedding context — Firecracker: Linux/KVM only, embedded into cloud orchestration software. crosvm: Linux/KVM as its home base, embedded into ChromeOS (Crostini), Android (AVF pVMs), and as an optional backend under gVisor's syscall-interception sandbox; broader backend ambitions exist given Google's multi-platform reach, but verify current support against crosvm's docs.
  • Intended unit of work — Firecracker: one of thousands of short-lived, headless server guests per host, created and destroyed by a scheduler. crosvm: one interactive Linux (or Android) environment a human or an app is actively using, for the length of a session.
  • Device model breadth — Firecracker: virtio-net/block/vsock, serial console, entropy source — nothing a headless workload doesn't need. crosvm: all of that plus virtio-gpu with GPU passthrough, virtio-wayland, audio devices, and other desktop/mobile-oriented virtio devices, because its guests are often full graphical environments.
  • Guest type — Firecracker: a process or a small service that never renders anything and has no concept of a display. crosvm: frequently a full Linux userland (or Android) with windows, a compositor, and sound.
  • Snapshot/restore maturity — Firecracker: first-class and production-hardened; it's the actual create path for every guest, not a debugging feature. crosvm: has explored snapshot support in some contexts, but this is not crosvm's primary design center the way it is Firecracker's — don't assume parity, verify against crosvm's current documentation.
  • Security model — Firecracker: minimal device surface plus a jailer plus seccomp, built explicitly for a "run untrusted code from strangers" multi-tenant cloud threat model. crosvm: also genuinely security-focused — Google cares a great deal about Chromebook and Android sandbox-escape resistance — but a larger device model is structurally more attack surface exposed to the guest, independent of how carefully each device is implemented.
  • rust-vmm relationship — Firecracker: an original rust-vmm contributor, still consumes shared crates, steered by its own cloud-sandboxing roadmap. crosvm: an original rust-vmm contributor, still consumes shared crates, steered by ChromeOS/Android/gVisor product needs.
  • Best fit — Firecracker: platforms and orchestrators running many untrusted, headless guests per host at fleet scale, where a REST API and snapshot-restore density are the product. crosvm: platform teams embedding a sandboxed Linux or Android environment into a consumer device or another sandbox's isolation stack, where GPU/audio/display support is a requirement, not a nice-to-have.

Boot speed, and why snapshot-restore is the real dividing line

Both VMMs skip legacy PC firmware and boot a Linux kernel about as directly as KVM allows, so raw boot time isn't where they separate. I won't publish a head-to-head number, because a fair one depends on kernel config, device count, storage backend, and host — and inventing a number for someone else's project is exactly how false benchmarks end up quoted as fact. What I'll claim instead is structural: snapshot-restore changes the shape of the create path, not just its speed, and Firecracker treats it as the default way a guest comes into existence. Freeze a booted VM to a memory file plus a state file once, then restore that exact machine on demand instead of booting Linux from scratch every time.

On PandaStack, that's the difference between roughly 3 seconds for a template's very first cold boot and a p50 of 179ms for every create after that (p99 around 203ms). It's also what makes cheap forking possible — 400–750ms same-host, 1.2–3.5s cross-host — because a restored memory image is mapped copy-on-write and the rootfs is a file you can reflink. crosvm's device model gives it plenty of reasons to care about fast VM startup too — nobody wants to wait for a Chromebook's Linux container to boot — but whether its snapshot support currently reaches the same "boot once, restore thousands of times, as the standard create path" design center is a question for crosvm's own docs, not an assumption to carry into an architecture.

The operational model, which is the real fork in the road

Picture what a cloud scheduler needs from a VMM it's placing the ten-thousandth guest of the hour with: a control surface any language can speak over the network, per-guest cgroups so one tenant's runaway process doesn't starve the host, per-guest network namespaces so tenants can't see each other's traffic, and a way to know a guest's state without asking the code that created it. Firecracker's REST-API-plus-jailer design exists specifically so a scheduler can own all of that from the outside. PandaStack pre-allocates 16,384 /30 subnets per agent host for exactly this reason — that bookkeeping wants to live in the orchestrator, addressed the same way for guest #1 and guest #16,000.

Now picture what ChromeOS needs: launch one Linux environment when a user opens their Linux Files app, keep it running while they work, give it a GPU so their IDE doesn't feel like a serial terminal, and tear it down when they log out. Or what AVF needs: spin up a protected VM as an isolation boundary inside an Android OS release, with a device set scoped to what that specific feature requires. Neither of those is "drive a fleet of interchangeable headless guests from an external scheduler" — they're "be the VM layer inside a product that already knows exactly one thing it wants to run." crosvm's CLI-and-control-socket interface, tied to its embedding context rather than exposed as a generic remote API, reflects that it was never trying to be the thing an arbitrary third-party orchestrator drives.

Where each one wins, plainly

Pick crosvm when

  • You're building a sandboxed, interactive Linux or Android environment for a person to use directly — windows, a compositor, sound — not a headless worker.
  • You need GPU-accelerated rendering inside the guest, via virtio-gpu, because the whole point is a usable graphical desktop or app inside the VM.
  • You're embedding a VMM into a larger platform you already control end to end — ChromeOS, Android's AVF, or a gVisor deployment wanting an extra KVM-backed isolation layer — rather than exposing it to a third-party orchestrator.
  • Your isolation boundary needs to sit specifically inside Google's ChromeOS/Android ecosystem, where crosvm is the maintained, product-integrated answer.
  • You want a VMM with more platform-backend ambition than Linux/KVM alone, given crosvm's broader multi-platform reach — verify current backend support in its docs before committing.

Pick Firecracker when

  • Your guests are headless, ephemeral, and server-side — no display, no audio, nothing a human is looking at — and a minimal device model is a security feature, not a missing one.
  • You need a general-purpose REST API that an arbitrary orchestrator, written in any language, can use to create, inspect, and destroy thousands of guests across many hosts.
  • You're running untrusted or model-generated code from many tenants, and you want the VMM itself jailed and seccomp-filtered by default, on top of the hardware virtualization boundary.
  • Create latency and density are the product, and snapshot-restore as the standard create path — not an occasional feature — is how you get both.
  • You're already committed to Linux/KVM as your only target and have no need for the desktop-oriented device model crosvm carries for ChromeOS and Android.

The third option: don't operate a VMM at all

Neither crosvm nor Firecracker is trying to answer the question a lot of teams actually have, which isn't "which VMM should we embed" but "how do we give an application an isolated Linux machine on demand, without becoming the team that operates VMMs." That's usually the shape of the problem for AI agents running arbitrary shell commands, or a platform executing a customer's build script — headless, ephemeral, security-sensitive, and needed as a function call, not a subsystem.

PandaStack is that layer, with Firecracker doing the actual virtualization underneath: snapshot-restore on every create instead of a warm pool of idle VMs you pay to keep around, a pre-allocated network namespace and tap device per sandbox, copy-on-write rootfs, and vsock into a guest agent. The jailer flags, the REST calls, the Unix socket — all of that is our problem, not your application's.

from pandastack import Sandbox

# No kernel to source, no jailer config, no VMM CLI to learn, no GPU
# or Wayland devices to reason about because there's nothing to
# render. Each sandbox is a real Firecracker microVM, created by
# restoring a baked snapshot (p50 179ms, p99 ~203ms).
with Sandbox.create(template="code-interpreter", ttl_seconds=600) as sbx:
    sbx.filesystem.write(
        "/work/report.py",
        b"import json\n"
        b"rows = json.load(open('/work/rows.json'))\n"
        b"print(sum(r['total'] for r in rows))\n",
    )
    sbx.filesystem.write("/work/rows.json", open("rows.json", "rb").read())

    run = sbx.exec("python /work/report.py", timeout_seconds=60)
    if run.exit_code != 0:
        raise RuntimeError(run.stderr)
    print(run.stdout)

    # Snapshot this exact machine -- deps installed, files staged.
    snap = sbx.snapshot()

    # Fan out variations from that warm state. Same-host fork lands
    # in 400-750ms, so "branch and compare N approaches" is a
    # for-loop instead of a fleet-management problem.
    for candidate in candidate_scripts:
        child = sbx.fork()
        child.filesystem.write("/work/report.py", candidate.encode())
        result = child.exec("python /work/report.py", timeout_seconds=60)
        record(candidate, ok=result.exit_code == 0, out=result.stdout)
        child.kill()
# Sandbox is destroyed on block exit; the snapshot outlives it.

If your problem looks like that snippet, the Firecracker-vs-crosvm question was never really yours to answer — you want a sandbox API, not a VMM to embed. And if instead you're shipping a sandboxed Linux desktop inside a Chromebook or an Android VM, crosvm's documentation is the right next stop, not this post.

Frequently asked questions

Is crosvm a Firecracker alternative?

Only in the narrow sense that both are VMMs built on rust-vmm. In practice they're aimed at different guests and different embedders. Firecracker is a standalone binary you supervise from a fleet orchestrator over a REST API, purpose-built to run thousands of headless server guests densely and safely. crosvm is embedded into ChromeOS, Android's Virtualization Framework, or gVisor, and its device model exists to support a graphical Linux or Android environment a human or an app actually uses. If you're building cloud sandbox infrastructure for headless workloads, Firecracker fits that job description; crosvm was built for a different one.

Does crosvm support GPU acceleration and Firecracker doesn't?

Yes, and it's one of the clearest structural differences between them. crosvm supports virtio-gpu with GPU passthrough/acceleration, plus virtio-wayland and audio devices, because it has to render a usable Linux desktop inside ChromeOS's Crostini feature and support interactive Android VMs. Firecracker has no graphics device of any kind by design — its guests are headless server processes with no display, so a GPU device would only be attack surface with no upside. Neither gap is a bug; each project's device model matches what its guests actually do.

Can I drive crosvm the way I'd drive a fleet of Firecracker VMs with a REST API?

Not in the way Firecracker was built for. Firecracker exposes a REST API over a Unix socket specifically so an arbitrary, language-agnostic orchestrator can create, configure, and destroy guests at fleet scale. crosvm's control surface is a CLI and control-socket interface tied to its embedding context — ChromeOS's VM manager, Android's AVF, or gVisor's platform layer drive it as part of their own product, not as a generic remote API meant for a third-party scheduler. Verify the current interface in crosvm's own docs before assuming it can slot into a Firecracker-shaped orchestration layer.

Is crosvm more or less secure than Firecracker?

They're both taken seriously as security boundaries by teams with strong incentives to get it right — AWS runs Lambda and Fargate on Firecracker, and Google relies on crosvm to contain Chromebook and Android sandbox escapes. The structural difference is attack surface shape: Firecracker's device model is deliberately minimal (network, block, vsock, console, entropy) plus a jailer and seccomp filter, purpose-built for a strangers'-untrusted-code threat model. crosvm necessarily exposes more virtio devices to the guest — GPU, Wayland, audio — because its guests need them, and more exposed devices is structurally more attack surface regardless of implementation quality. Neither claim is about code quality; it's about how much surface each design has to defend.

Does crosvm support snapshot and restore like Firecracker does?

Don't assume parity — verify against crosvm's current documentation before designing around it. What's confidently true is that Firecracker treats snapshot-restore as first-class and production-hardened: it's the actual path used to create every guest, not an add-on feature, and it's why PandaStack can hit a p50 of 179ms per create after a template's first ~3 second cold boot. crosvm has explored snapshot capability in some contexts, but matching a full Linux or Android desktop's runtime state — GPU context, Wayland session, audio state — to a restorable snapshot is a harder and different problem than snapshotting a headless server process, and it isn't crosvm's primary design center the way it is Firecracker's.

Run code in a microVM in one API call.

49ms p50 cold start. Fork, snapshot, and scale to zero.

Start free
Written by Ajay Kumar, Founder, PandaStack.