Architecture

// ARCHITECTURE

Three execution layers — one per bug.

Layer 1 browser-native WebAssembly, Layer 2 containers, Layer 3 record-replay. The recipe declares which layer it runs on — you don't pick. The matrix below scans the trade-offs at a glance; the deep-dive sections follow.

L1 / WASM

In the browser, instantly.

L2 / DOCKER

Docker / microVM, for fidelity.

L3 / RECORD-REPLAY

Trace bundled, replay anywhere.

Startup
ms to a few seconds. First load 1–10 s for the runtime download (Pyodide ≈ 10 MB); cached loads under 1 s.
Seconds to minutes. Catalogue distribution — runs on the visitor's Docker or Codespaces.
Seconds to minutes (replay only). Recording is offline-only on the Vivarium side; visitors just rr replay.
Bugs it fits
Algorithms, data processing, DB queries, library-internal logic.
Whole-project repros, syscall-dependent, toolchain-specific, multi-process.
Data races, memory ordering, long-replay scenarios, distributed bugs depending on a specific interleave.
Can't reach
Memory ceiling ~4 GB, real fork/exec, data races, building the compiler itself.
Cannot run on the page itself; needs Docker or Codespaces; heisenbug reliability is L3 territory.
Linux/x86_64 only (ARM/Windows fall back to Codespaces or WSL2); traces from tens of MB to single-digit GB.
Runtimes
Pyodide / Ruby.wasm / php-wasm / wasm32-wasip1 / sqlite-wasm.
Pinned Dockerfile + ghcr.io/aletheia-works/vivarium-<slug> + Codespaces badge.
Self-contained GHCR images with the rr trace baked in.
L1 / WASM

// 01 · LAYER 1

WebAssembly, in the page.

Reproductions run directly inside your browser tab. No account, no install — open the page and it starts. Phases 0–2 built up Python / Ruby / PHP / Rust recipes, e.g. cpython#137205 and pandas#56679; this layer is the most "browser-only" surface Vivarium ships.

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/exec or 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.

Runtimes and live examples

L2 / DOCKER

// 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.
L3 / RECORD-REPLAY

// 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. rr targets 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.

Live examples

  • pthread lost-update — a real pthread race captured deterministically; visitors only rr replay.
  • New Layer 3 recipes need offline PMU recording, so the cadence is slower than L1 / L2.

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.

// NEXT

See real examples

The reproductions gallery shows live recipes for each layer.

VIVARIUM is part of ALETHEIA-WORKS · See the source on GitHub →