Skip to content
Fuse
Esc
navigateopen⌘Jpreview
On this page

Providers: Firecracker vs QEMU

The two virtualization backends Fuse schedules onto, and how they differ

A provider is what actually creates and manages microVMs on a host. Fuse ships two: Firecracker, the default CPU backend, and QEMU, the optional GPU-passthrough backend. Both implement the same internal Provider interface, so the orchestrator schedules onto either uniformly. The difference shows up in what each backend can and can’t do.

Firecracker (default)

Firecracker is the default backend for ordinary CPU workloads. It talks to fc-agent, a per-host Python process that drives one Firecracker process per VM, over an HTTP contract (POST /v1/vm, upload/exec, start-agent, snapshot/restore). See Artifacts for how the guest rootfs and agent get onto a Firecracker host, and Firecracker host setup for bringing one up.

QEMU (GPU passthrough)

QEMU is the backend for GPU environments. It mirrors the Firecracker provider’s shape but drives QEMU/KVM with VFIO passthrough instead of Firecracker microVMs. A host opts into it at registration time with --backend qemu.

It serves GPUs two ways. Whole-device passthrough attaches every PCI function in a GPU’s IOMMU group to the guest, which is what a Fusefile requests with gpu: 1 and no profile. Fractional passthrough attaches a pre-created MIG instance as an mdev device, which is what gpu_profile: 1g.10gb requests. The two draw on separate inventories on the host, a MIG request never consumes a whole device from the passthrough pool and vice versa, so a host can serve both at once.

The key limitation: QEMU environments cannot snapshot or fork. A GPU passed through via VFIO can’t be checkpointed the way a Firecracker microVM’s disk can, so snapshot and fork requests against a QEMU-backed environment fail cleanly rather than silently no-op. See Snapshots for the full snapshot model and this exception.

See GPU host setup for IOMMU/VFIO bring-up.

Stub mode

Both providers fall back to an in-memory stub implementation when no real host is configured (empty FIRECRACKER_BASE_URL, or explicit stub mode in tests); it simulates provider behavior without booting real microVMs. This is what the Quickstart uses, and it’s the default for local dev and the orchestrator’s own test suite. The orchestrator logs which mode it’s running in at boot.

Local development is not a third backend

fuse local runs environments on your own machine, but it adds no new provider: it is the Firecracker backend pointed at a host agent running locally (on Linux, directly against /dev/kvm; on macOS, inside a small appliance VM). The scheduler, the wire contract, and the agent are the production ones, which is the point — anything that works locally works against a fleet because it is the same code path, not a compatible one.

Choosing a backend

Backend selection happens once, at host registration time:

# firecracker, the default backend
fuse host register my-host --url http://10.0.0.5:8090 \
  --token "$FC_AGENT_TOKEN" --backend firecracker --max-vms 20

# qemu, for GPU hosts
fuse host register gpu-1 --url http://10.0.0.9:8091 \
  --token "$QEMU_AGENT_TOKEN" --backend qemu --gpus 1 --gpu-kind a100 --max-vms 4

--token is the host agent’s own token, and --max-vms is a scheduling ceiling that is never probed, so both are required on every registration.

A Fusefile’s resources.gpu / resources.gpu_kind / resources.gpu_profile fields don’t name a backend directly; a non-zero gpu count is what routes the environment to a host with matching free GPU inventory (necessarily QEMU-backed, since only QEMU hosts report GPU capacity). CPU-only requests schedule onto Firecracker hosts. A GPU request fails fast rather than waiting for capacity that may never appear. With no hosts registered at all the error is gpu workloads require a registered gpu host; with hosts registered but none offering free matching GPU inventory, including a fleet of only CPU-only Firecracker hosts, it is no host has sufficient capacity followed by the requested figures. Both return 503.

Was this page helpful?