This episode covers microVM resource control: the balloon device for reclaiming memory from the guest, balloon and MMIO statistics, virtio-rng for guest entropy, per-device rate caps, and cgroup v2 to limit CPU and memory at the host level.

In episode 9 we could freeze and revive microVMs. Now the subtler challenge: how do hundreds of microVMs share one host fairly? Episode 10 covers resource control — memory via the balloon device, entropy via virtio-rng, and hard CPU/memory limits via cgroup v2.
Why is this episode important? Without resource control, a single microVM could drain all memory or monopolize the CPU, taking down its neighbors. With the balloon and cgroups, operators can specify precisely how many resources each VM may use — the foundation of the multi-tenant economics that make Firecracker viable at AWS scale.
The virtio-balloon device is Firecracker's mechanism for reclaiming memory from the guest back to the host. The concept: the host "inflates" the balloon inside the guest, pushing the guest to release unused memory pages; those pages return to the host pool and can be used by other VMs.
Configure the balloon before boot:
curl --unix-socket /tmp/firecracker.sock -i \
-X PUT http://localhost/balloon \
-H 'Accept: application/json' -H 'Content-Type: application/json' \
-d '{
"amount_mib": 128,
"deflate_on_oom": true,
"stats_polling_interval_s": 10
}'Important fields:
amount_mib — how many MiB of memory to pull back from the guest (the balloon inflates by this amount).deflate_on_oom — when the guest runs low on memory (OOM), the balloon automatically deflates to give memory back — a safety net that prevents the guest from being killed.stats_polling_interval_s — the interval for collecting guest memory statistics.The balloon size can be changed dynamically after boot via PATCH /balloon — inflate when a VM is idle, deflate when it needs more:
curl --unix-socket /tmp/firecracker.sock -i \
-X PATCH http://localhost/balloon \
-H 'Accept: application/json' -H 'Content-Type: application/json' \
-d '{ "amount_mib": 512 }'Warning
The balloon works with the guest's cooperation: the balloon driver inside the guest (built into the Linux kernel) decides which pages to release. A guest without the driver, or a guest that refuses to release memory, won't be effective — and deflate_on_oom is the only safety net if the balloon is too aggressive. Never "inflate" the balloon beyond the memory the guest genuinely needs.
Balloon statistics give you a window into guest memory conditions from the host side. With stats_polling_interval_s active, the host can read:
curl --unix-socket /tmp/firecracker.sock http://localhost/balloon/statisticsThe output is JSON containing metrics like free_memory, available_memory, pages_reclaimed — data an orchestrator can use to decide when to inflate/deflate the balloon automatically. This is the same control loop pattern as memory reclamation in modern hypervisors: monitor → decide → adjust.
Firecracker maps the balloon device via MMIO, just like the other virtio devices. That means it follows the same rules: configurable only before boot, and it runs as a standard virtio device the guest kernel recognizes.
A freshly spawned microVM often lacks entropy — the source of randomness for cryptography (TLS, UUIDs, keys). The host has getrandom and hardware RNGs; a guest inside a VM doesn't automatically get access to them. Without entropy, cryptographic processes in the guest can block waiting for randomness.
The solution is the virtio-rng device, enabled by default in Firecracker's configuration, which injects entropy from the host into the guest. Its configuration can be tuned through the machine config:
curl --unix-socket /tmp/firecracker.sock -i \
-X PUT http://localhost/machine-config \
-H 'Accept: application/json' -H 'Content-Type: application/json' \
-d '{
"vcpu_count": 2,
"mem_size_mib": 1024,
"entropy": { "rate_limiter": { "ops": { "size": 1000, "refill_time": 100 } } }
}'Check entropy inside the guest:
cat /proc/sys/kernel/random/entropy_availIf the number is high and never stalls, virtio-rng is working. Note too that a rate limiter can be applied to the entropy device — preventing a single VM from draining the host's entropy source with excessive requests.
The balloon is persuasive (it asks the guest to release memory). cgroup limits are enforced — at the kernel level, without guest cooperation. With cgroup v2, each microVM is placed in its own cgroup:
mkdir -p /sys/fs/cgroup/fc/<id>
echo 1024 > /sys/fs/cgroup/fc/<id>/memory.max
echo 500000 > /sys/fs/cgroup/fc/<id>/cpu.maxReading these values:
memory.max — maximum memory (bytes) for the group. If exceeded, the kernel reclaims; if it can't, OOM-kill happens inside the group.cpu.max — in quota period format (e.g. 500000 100000 = 500 ms per 100 ms period = 5 vCPUs).cpuset.cpus — choose which CPUs can be used, helping isolation and NUMA.Then place the Firecracker process into the cgroup:
echo <firecracker-pid> > /sys/fs/cgroup/fc/<id>/cgroup.procsThe jailer already creates a base cgroup for each VM; with cgroup v2, operators extend it with explicit limits. The combination of balloon + cgroup is the complete pattern:
The two work at different layers and complement each other.
Besides cgroups, every I/O device has its own limits via the rate limiter (covered in episode 5). The complete resource control map:
cpu.max + the vCPU choice in the machine config.memory.max + balloon amount_mib.bandwidth + ops rate limiters on the network interface.bandwidth + ops rate limiters on the drive.With this map, operators can give measurable service promises per VM — and enforce them across several layers at once.
Tip
Start with loose numbers: cgroup limits above your estimated peak usage, the balloon only for genuinely idle memory. Being too strict from the start causes OOM-kills and degradation that are hard to debug. Tighten as data comes in.
deflate_on_oom false: risk of the guest being killed under memory pressure; enable it unless there's a strong reason not to.memory.max > mem_size_mib + overhead.stats_polling_interval_s must be set for statistics to be collected.The key takeaways:
deflate_on_oom prevents OOM in the guest when the balloon is too aggressive.entropy_avail.cpu.max) and memory (memory.max) limits.In the next episode 11 we'll bridge Firecracker with the container world: Container Integration — firecracker-containerd — the containerd runtime that runs each container inside its own Firecracker microVM, understanding the runtime and overlay snapshotter components, and the pull → unpack → run flow of running a container in a microVM with bridge networking.