The Firecracker runtime
Every Tabbify app runs as a detached runner process hosted by a supervisor. What that runner does inside is boot a Firecracker microVM built from your OCI image — and that is the one and only runtime Tabbify ships. You don't pick a runtime; there's nothing to choose.
One runtime: Firecracker
Your Dockerfile is built into an OCI image, that image is unpacked into an
ext4 rootfs, and Firecracker boots a microVM that runs the image's entrypoint.
Each app gets its own kernel and rootfs, so apps are isolated from each other and
from the host at the VM level. Firecracker only runs on a Linux supervisor with
/dev/kvm — on a host without KVM, placement fails by design (see
Capability detection below).
This single-runtime model is intentional. There is no in-process WASM runtime and no bare-container runtime to weigh against it: the build always produces an OCI image, and the OCI image always runs as a Firecracker microVM. A first request after a deploy (or after a long idle) waits a moment while the VM boots; every request after that is fast.
A note on legacy tabbify.toml fields
Older tabbify.toml files sometimes carried a [runtime] type = "..." value or
a per-deploy runtime = "..." override (for example "wasm-http" or
"docker"). Those keys are tolerated for wire-compatibility and ignored —
they no longer select anything. Whatever they say, the app builds an OCI image
and runs as Firecracker. You can leave them in an old manifest, but new manifests
should omit them.
Likewise, [build].kind is always docker (build the Dockerfile into an OCI
image). It controls the artifact, not the runtime.
What [runtime] actually configures
The [runtime] section sets the microVM's lifecycle and resource limits — not a
runtime choice. See the tabbify.toml manifest for the full
schema.
[runtime]
lifecycle = "on_request" # always_on | on_request
idle_timeout_sec = 300
memory_mb = 512
vcpus = 1
lifecycle—always_onkeeps the VM running;on_requeststarts it on the first visit and stops it afteridle_timeout_secof inactivity.memory_mb/vcpus— the microVM's memory and CPU allocation.
Capability detection
A supervisor only advertises what it can actually host. It adds the firecracker
tag if /dev/kvm is readable, the docker tag if a Docker daemon is reachable
(used for building images), and the builder tag if the operator designated it
as a build host. These show up as mesh tags, and the node
refuses to place an app on a supervisor that lacks the firecracker capability —
the match is on capability, not on a per-app runtime choice:
curl -H 'Authorization: Bearer <TABBIFY_TOKEN>' https://api.tabbify.io/v1/supervisors
# [{"display_name":"ec2-prod","tags":["supervisor","docker","builder"]},
# {"display_name":"thinkpad","tags":["supervisor","firecracker","docker"]}]
In this example, an app would be placed on thinkpad (it advertises
firecracker), while ec2-prod serves as a build host. Add more Firecracker-
capable supervisors and the node spreads placement across them.
The Firecracker runtime is implemented and proven in production runners, verified
live on Linux hosts with real KVM. Wherever an app lands, it gets a stable
private mesh address (a deterministic per-app ULA, e.g.
fd5a:1f02:…::1) and the runner contract — health, restart, lifecycle — stays
the same.