The isolation-vs-speed dilemma
For running untrusted code, you face a classic trade-off. Containers are fast and cheap but share the host kernel — a weaker security boundary. Full virtual machines give you hardware-enforced isolation (each VM has its own kernel) but they're heavy: gigabytes of memory, seconds to boot, a full virtual hardware stack to emulate.
Serverless and multi-tenant platforms needed both: VM-grade isolation *and* near-instant start. The answer is the microVM.
What a microVM actually is
A microVM is a virtual machine deliberately stripped to the minimum. It runs on a hardware virtualization layer (KVM on Linux), so it has its own guest kernel and hardware-enforced isolation — but it throws away nearly everything a traditional VM emulates.
The component that creates and runs the VM is the Virtual Machine Monitor (VMM). A traditional VMM like QEMU emulates a rich set of virtual hardware: BIOS, PCI bus, USB, sound, legacy devices, a graphics card. All of that is code, attack surface, and boot time you don't need to run a web service.
A microVM VMM like AWS Firecracker does the opposite. It implements only:
- A minimal set of virtio devices (network, block storage, vsock).
- A simple serial console and a one-button keyboard controller (just enough to boot and stop).
- No BIOS, no PCI, no USB, no emulated graphics.
Less emulated hardware means a smaller attack surface, lower memory overhead, and a dramatically faster boot.
How it boots in milliseconds
Firecracker famously boots a microVM in well under a second — AWS documents sub-125ms to a running guest under typical configurations. Several design choices make that possible:
- 1No firmware/BIOS phase. Firecracker loads an uncompressed Linux kernel directly and jumps in, skipping the slow firmware handshake real and traditional-virtual hardware require.
- 2Tiny device model. There's almost nothing to initialize.
- 3Written in Rust for memory safety, as a single lightweight process per microVM.
- 4A minimal guest (a small kernel + a purpose-built root filesystem) that boots straight to the workload.
Low per-VM memory overhead (single-digit MBs of VMM overhead) means you can pack thousands of microVMs onto one host — which is the economic requirement for serverless.
microVM vs container vs VM
| Container | microVM | Traditional VM | |
|---|---|---|---|
| Isolation boundary | Shared host kernel | Own kernel (HW-enforced) | Own kernel (HW-enforced) |
| Boot time | milliseconds | ~tens–hundreds of ms | seconds–minutes |
| Memory overhead | minimal | low (few MB VMM) | high (full OS) |
| Density per host | very high | high | low |
| Emulated hardware | none | minimal | full |
| Best for | trusted workloads | untrusted/multi-tenant fast start | legacy/full-OS needs |
The microVM occupies the sweet spot: container-like speed and density with VM-like isolation.
Why this matters: serverless and runners
The reason microVMs exist commercially is multi-tenant serverless. AWS Lambda and Fargate run customer workloads on Firecracker microVMs — that's how they safely run thousands of different customers' code on shared hardware while still starting functions fast.
The same property makes microVMs ideal for CI/CD runners. A self-hosted GitHub Actions runner that boots a fresh, isolated microVM per job gets you:
- A clean environment every run (no state leakage between jobs).
- Hardware isolation between potentially untrusted PR code.
- Fast enough boot that the isolation is essentially free in wall-clock terms.
This is exactly the model behind FireRunner's Firecracker-based runners, and it's why static-site builds on PandaStack run inside microVMs on the pandastack.ai build layer: each build gets an isolated, fast-booting environment rather than sharing a long-lived builder. Container app builds, by contrast, use rootless BuildKit in ephemeral Kubernetes Job pods — different tool, same principle of ephemeral isolation.
A minimal Firecracker boot
Firecracker is configured over a REST API on a local Unix socket. The essence:
# Start firecracker listening on a socket
firecracker --api-sock /tmp/fc.sock &
# Set the kernel + boot args
curl --unix-socket /tmp/fc.sock -X PUT 'http://localhost/boot-source' \
-d '{"kernel_image_path":"vmlinux","boot_args":"console=ttyS0 reboot=k panic=1 pci=off"}'
# Attach a root filesystem
curl --unix-socket /tmp/fc.sock -X PUT 'http://localhost/drives/rootfs' \
-d '{"drive_id":"rootfs","path_on_host":"rootfs.ext4","is_root_device":true,"is_read_only":false}'
# Start the microVM
curl --unix-socket /tmp/fc.sock -X PUT 'http://localhost/actions' \
-d '{"action_type":"InstanceStart"}'Notice pci=off in the boot args — that's the "no PCI bus" minimalism in action.
The honest limitations
- You manage the guest. No firmware means you supply a compatible kernel and rootfs; it's lower-level than running a container.
- Narrow device support is the point, but it means workloads needing exotic hardware/devices don't fit.
- Nested virtualization caveats — microVMs want bare-metal or virtualization-capable hosts (KVM).
For the workload microVMs target — fast, isolated, ephemeral execution of code you don't fully trust — none of these matter, and the benefits are transformative.
References
- [Firecracker official site](https://firecracker-microvm.github.io/)
- [Firecracker design document](https://github.com/firecracker-microvm/firecracker/blob/main/docs/design.md)
- [Firecracker NSDI 2020 paper (AWS)](https://www.usenix.org/conference/nsdi20/presentation/agache)
- [KVM (Kernel-based Virtual Machine) documentation](https://www.linux-kvm.org/page/Main_Page)
- [virtio specification](https://docs.oasis-open.org/virtio/virtio/v1.2/virtio-v1.2.html)
---
PandaStack builds static sites inside fast-booting microVMs and runs container apps in isolated, ephemeral pods — you just push code. See it work on the free tier at [dashboard.pandastack.io](https://dashboard.pandastack.io).