Documentation
ReferenceArchitecture

Runtimes: WASM, Firecracker, Docker

Every Tabbify app runs as a detached runner process hosted by a supervisor. What that runner does inside — execute a WASM component, boot a microVM, or run a container — is the runtime, and you pick it per deploy target.

Three runtimes

  • wasm-http — your code as a WASI-HTTP component, executed in-process by wasmtime. Lightest and fastest to start; runs everywhere, no host privileges needed.
  • firecracker — a microVM with its own kernel and ext4 rootfs, built from your OCI image. Strong isolation; needs Linux with /dev/kvm.
  • docker — a plain container via the host Docker daemon. The most familiar path; runs anywhere Docker does.

A key design point: runtime is chosen at deploy time, not baked at build time. The same Docker image can run as a container on one supervisor and a Firecracker microVM on another. Your [build].kind (docker or wasm) decides the artifact; the runtime decides how it executes.

Choosing one

WantUse
Smallest cold start, runs anywherewasm-http
Container isolation, fast iterationdocker
VM-grade isolation for untrusted codefirecracker

WASM cold-starts in under a second; Firecracker boots in roughly two. Both wasm-http and docker run on any host. Firecracker only runs on a Linux supervisor with KVM — on macOS or a nested VM without /dev/kvm, it fails by design.

Set it in tabbify.toml

Pick a default in [runtime], then override per target in each [[deploy]] block. See the tabbify.toml manifest for the full schema.

[runtime]
type             = "docker"      # docker | firecracker | wasm-http
lifecycle        = "on_request"  # always_on | on_request
idle_timeout_sec = 300
memory_mb        = 512

[[deploy]]
supervisor = "ec2-prod"
runtime    = "docker"

[[deploy]]
supervisor = "thinkpad"
runtime    = "firecracker"   # same image, VM isolation here

Capability detection

A supervisor only advertises what it can actually run. It always offers wasm-http; it adds docker if the daemon answers and firecracker if /dev/kvm is readable. These show up as mesh tags, and the node refuses to place an app on a supervisor that lacks the requested runtime:

curl -H 'Authorization: Bearer <KEY>' http://3.124.69.92:8090/v1/supervisors
# [{"display_name":"ec2-prod","tags":["supervisor","docker"]},
#  {"display_name":"thinkpad","tags":["supervisor","firecracker","wasm-http"]}]

All three runtimes are implemented and proven in production runners: WASM and Docker are mature, and Firecracker has been verified live on Linux hosts with real KVM. Whichever you pick, the app lands on a stable private mesh address and the runner contract — health, restart, lifecycle — stays the same.