Firecracker Snapshot/Restore: 1,165ms to 28ms
The Numbers
| Metric | Before | After | Improvement |
|---|---|---|---|
| Single spawn | 1,165ms | 28ms | 41x faster |
| 3 concurrent spawns | 3,495ms sequential | 43ms wall clock | 81x faster |
| Provider | Cold Start |
|---|---|
| AWS Lambda | ~200-500ms |
| E2B | ~300-600ms |
| Fly Machines | ~300ms |
| Modal | ~100-200ms |
| StacyVM | 28ms |
Where the Time Was Going
How Snapshot/Restore Eliminates It
How It Works
The Golden Image Pattern
Once per image (background, ~1.5s):- Boot a temporary VM from the rootfs
- Wait for the guest agent to become ready
- Pause the VM (
PATCH /vm {"state": "Paused"}) - Snapshot:
PUT /snapshot/createproducesvmstate.bin(CPU/device state, 16KB) +memory.bin(full RAM, 512MB) - Kill the temporary VM, keep the snapshot files
- Sparse-copy the snapshot’s clean rootfs to a new sandbox directory
- Start a fresh Firecracker process (no VM config needed)
PUT /snapshot/loadwithresume_vm: true— VM resumes instantly- Connect to the already-running guest agent over vsock
The Relative Path Trick
Firecracker bakes drive and vsock paths into the snapshot state. You cannot reconfigure them before or after loading a snapshot. This seems like a dealbreaker for running multiple VMs from one snapshot. The solution: use relative paths during snapshot creation.cmd.Dir set to its sandbox directory. When a snapshot is loaded, Firecracker resolves rootfs.ext4 and v.sock against its working directory. Each restored VM gets its own rootfs and vsock automatically — no path conflicts, no reconfiguration needed.
Snapshot Storage
Concurrency
Each restore is fully independent:- Own Firecracker process
- Own sandbox directory with own rootfs copy
- Own vsock UDS (relative path resolves to own dir)
- Own CID from atomic counter
What We Learned the Hard Way
-
/vmis PATCH, not PUT. Firecracker returns 400 with a cryptic “Invalid request method” error if you use PUT to pause/resume. - No drive/vsock config with snapshots. Firecracker rejects snapshot load if you configured any “boot-specific resources” beforehand. The error message (“Loading a microVM snapshot not allowed after configuring boot-specific resources”) doesn’t tell you that you also can’t configure them after load.
- Relative paths are the key. Every production Firecracker deployment using snapshots needs this trick. The snapshot state stores the exact paths used during creation. Relative paths + per-sandbox working directories = unlimited concurrent restores from one snapshot.
Files Changed
| File | What |
|---|---|
internal/providers/firecracker.go | snapshotInfo, createBaseSnapshot(), restoreFromSnapshot(), getSnapshot(), modified Spawn() |
internal/providers/firecracker_api.go | Added patch() method for PATCH requests |

