Architecture
// ARCHITECTURE
Three execution layers.
Which layer fits your bug — Layer 1 browser-native WebAssembly, Layer 2 containers, Layer 3 record-replay. Each is good at a different kind of bug.
// 01 · LAYER 1
WebAssembly, in the page.
Reproductions run directly inside your browser tab. No account, no install — open the page and it starts.
Bugs this layer fits
- Algorithmic bugs (sorting, parsing, text processing).
- Data-processing regressions (pandas / polars / numpy shape bugs).
- Database behavioural bugs (SQLite query anomalies, JSON path edge cases).
- Library-internal logic where the repro doesn't touch the filesystem, network, or process model.
Startup time
- Cold load (no cache): 1–10 seconds. Dominated by runtime download (Pyodide ≈ 10 MB compressed) and instantiation.
- Warm load (cached): under a second.
- Per-run execution: milliseconds to a few seconds.
What this layer can't reach
- Memory. A browser tab degrades past ~1 GB peak; ~4 GB is the practical ceiling. Production-scale data goes to Layer 2.
- System calls. No real
fork/execor real sockets. The WASI shim covers common cases, not all. - Concurrency bugs. Single-threaded by default — data races and heisenbugs go to Layer 3.
- Compiler builds. A Rust bug reproduces fine in-browser, but building the Rust compiler itself is Layer 2.
Supported runtimes
| Language | Runtime |
|---|---|
| Python | Pyodide |
| SQLite | sqlite-wasm (via Pyodide) |
| Rust | wasm32-wasip1 |
| Ruby | Ruby.wasm |
| PHP | php-wasm |
// 02 · LAYER 2
Docker / microVM, on your own machine.
For bugs that need a real filesystem, real processes, and real networking. Vivarium does not host execution; recipes are distributed as a catalogue that runs on your own Docker (or Codespaces).
Bugs this layer fits
- Whole-project reproductions — bugs that require dependency resolution against real package indexes.
- Syscall-dependent bugs — real
fork, real sockets, real file locks, real signals. - Toolchain-specific bugs — quirks of a specific GCC, glibc, or kernel ABI.
- Multi-process bugs where the interaction between processes is the bug.
How to use it
Each recipe page ships a pinned Dockerfile, a copy-pasteable
docker run … command, and a link to a published image at
ghcr.io/aletheia-works/vivarium-<slug>. The page also
shows the latest CI verdict snapshot — your own docker run
becomes the live confirmation. Where applicable an "Open in Codespaces"
badge is provided.
What this layer can't reach
- No in-page execution. The repro runs locally or in Codespaces, not on the gallery page.
- Docker (or Codespaces) required. Without either, you can still browse recipes and verdict snapshots.
- Concurrency itself. Layer 2 runs on real threads, but reproducing heisenbugs reliably is Layer 3 territory.
// 03 · LAYER 3
Trace bundled, replay anywhere.
For heisenbugs — bugs that don't reliably reproduce on a fresh re-run. Vivarium pre-records the trace, bakes it into a GHCR image, and you only have to replay.
Bugs this layer fits
- Data races, memory ordering bugs, use-after-frees that resist a fresh re-run.
- Long-replay scenarios: rewind hours of captured execution in minutes.
- Distributed-system bugs that depend on a specific message interleaving.
- Post-mortem forensic analysis — stepping backwards through a recorded trace.
How to use it
Each Layer 3 recipe ships as a self-contained GHCR image with the trace
baked in. rr replay doesn't need a PMU, so replay runs on
commodity Linux hosts — both for visitors and for CI.
The recording itself does need a PMU-equipped Linux/x86_64 host, but that
is done offline by Vivarium when the recipe is added — not something you
have to repeat.
What this layer can't reach
- Environment. Visitors need Linux/x86_64. ARM Mac or Windows users fall back to Codespaces or WSL2 + Docker.
- Coverage shape.
rrtargets single-process Linux x86_64; distributed-simulation tools target distributed systems — neither covers the other's territory. - Trace size. Tens of MB to single-digit GB per recipe.
Which layer a recipe runs on is declared by the recipe itself. You don't pick — opening the page runs it on the right layer automatically.