Amazon's Firecracker microVM only runs on Linux. When maintainers refused macOS support, Encore wrote its own bridge and a shared Linux build host.
For four years, every production build at Encore has run inside a Firecracker microVM, the stripped-down Linux hypervisor Amazon open-sourced in 2018 and now uses to power AWS Lambda and Fargate. The constraint sits inside the hypervisor: Firecracker drives KVM, the Linux kernel's virtualization interface, and no Mac ships with /dev/kvm.
Firecracker is a minimal VMM designed to boot microVMs in 125 ms or less, with a small attack surface and a stripped-down device model. That makes it a fit for multi-tenant serverless platforms, where each function gets its own kernel and the cost of a slow boot is paid on every cold start. Encore standardized on it for the same reason. Every build runs in its own microVM, the same way a Lambda function runs in its own, and the boot cost is amortized across the build.
Last year the Firecracker maintainers turned down a working macOS proof of concept built on Apple's Virtualization.framework and stated they have no plans to support macOS any time soon. Encore's engineers develop on Macs. The team built the bridge between the two systems themselves.
That bridge is crackling, their own microVM driver with a single API and two backends. On Linux production boxes it drives Firecracker directly. On a developer's Mac it drives Apple's Virtualization.framework. Same calling code, same VM images, two different hypervisors underneath.
The maintainers' reasoning, summarized in the GitHub discussion, focuses on the cost of supporting a second hypervisor backend inside a project whose design assumes a single one. macOS support would mean maintaining two code paths for the device model, the block layer, and the virtio stack, with no upstream CI matrix to test both. The discussion also flags that macOS Virtualization.framework exposes a different subset of features than KVM does, so even a working PoC only covers a slice of what Firecracker users run in production.
The hard half of Encore's work was the images, not the API. Firecracker boots a block device. Docker produces layers. Nothing off the shelf converted one to the other, so Encore wrote its own pipeline. Captured in tools/dev-builder/deploy-dev-builder.sh in the project repo, the pipeline runs docker save on a host image and pipes the resulting tar through a custom extractor that lands each layer in the right place. Booting the same images on both platforms also required rebuilding a chunk of the Linux image toolchain to run on macOS.
The rest of the post covers the workflow in detail. Every Encore engineer develops on a Mac. Their builds run on a shared Linux host in the company's datacentre. A one-shot onboarding script SSHes into that box as root, pulls the engineer's public key from https://github.com/<you>.keys, creates a local user, adds it to the kvm and docker groups, and hard-links the firecracker binary plus a copy of the VM images under the engineer's home directory. Binaries are cross-compiled on the Mac with GOOS=linux GOARCH=amd64, rsynced across, and the file count is what the system uses to decide whether anything needs restarting.
Per-engineer state, including the SSH port and the local username, lives in a gitignored CUE config, an open-source data-validation language. The file is gitignored because the host is shared across the team. Personal environments are reachable over Tailscale, sitting next to every other engineer's environment on the same rack. Tailscale is also what lets the team skip the per-engineer firewall rules a normal shared host would need.
The tradeoffs the post itself surfaces are real. SSHing as root into a shared host because the workaround demands it is not something to copy. A per-engineer collision-avoidance port file is the kind of detail that exists only because the team has no alternative. The Docker-to-block-device converter exists because no off-the-shelf tool does the job, which is also why Encore does not recommend anyone else follow the same path. The write-up is a record of a specific gap and a specific answer, not a template.
Reactions on Hacker News picked out exactly that tension. Several commenters noted the post itself reads as if it were partly AI-drafted; the technical specifics hold up while the surrounding chatter does not. The community split between readers who see the work as a clever fix for a real constraint and readers who see the operational cost as too high to recommend. The answer, like the workflow, sits with the team that built it.
When an upstream open-source project says no, the work does not disappear. It lands on a small team as a custom VM driver and a shared-root build host.