Rewind VM is a deterministic virtual machine created to debug race conditions in Nix builds by making each build run a pure function of its inputs, including the thread schedule. Farid Zakaria's blog post describes how the tool helps identify and solve race conditions through features such as a source panel, stack frames, GDB integration, a Compare tab that shows diverging events between runs, and a “Check from here” command that forks execution at a chosen step and tests many thread schedules to expose problematic interleavings. The tool’s core purpose is to provide a reproducible execution environment where the only variable is the order of thread scheduling, allowing the precise isolation of concurrency bugs.

Comparison view showing divergent thread 3 writes between failing and passing runs at step 3,250
In the failing run, thread 3 writes 'teller 2: 150 + 10' while the passing run writes 'teller 2: 200 + 10' at the same stepfzakaria.com

This image illustrates the Compare tab feature described in the first paragraph, which highlights diverging events between runs to identify race conditions.

GDB pane displaying a hardware watchpoint on balance variable at bank.c line 26
Thread 3 hits the hardware watchpoint with old value 200 and new value 160 in deposit, teller=2, at bank.c:26fzakaria.com

This image shows the GDB integration feature mentioned in the first and second paragraphs, enabled by debug information from nixpkgs.

To achieve reproducibility, Rewind treats the build under analysis as a Nix derivation and uses Nix’s knowledge of the derivation’s complete input set—source code, compiler, libraries, kernel, and the VM configuration. It realizes these inputs, packs them into a read‑only erofs image, and boots the VM on that image, ensuring that every run starts from an identical foundation. Each run is identified by a hash of its inputs, the same mechanism Nix uses for store paths. Separately, Rewind leverages the debug information that nixpkgs produces: packages are built with separate debug data cached on cache.nixos.org, which can be fetched by build ID using the debuginfod service. This lets Rewind display the exact source of any binary running inside the VM—including the Linux kernel—at any execution step, powering the source view, stack frames, and GDB integration without requiring the tool to manage symbol resolution independently.

Source panel showing bank.c line 24 and call stack from __syscall_cancel_arch to clone3
At step 3,250 of the failing bank run, the source panel displays bank.c open at line 24 with the write in deposit and the full stack tracefzakaria.com

This image demonstrates the source panel and stack frame inspection powered by Nix-derived debug data, as discussed in the second paragraph.

While Nix supplies the immutable inputs and debugging data, Rewind adds the ability to perturb thread schedules to uncover race conditions that might not appear in a single run. The “Check from here” feature, for example, forks a run at a specific step and re‑executes the remainder under many different schedules, counting how many outcomes differ; in the bank example, 16 out of 16 perturbed schedules led to a failed balance, demonstrating the systematic exposure of the bug. However, this approach is inherently limited to software that can be built and executed within a Nix sandbox, and it assumes that all nondeterminism originates from thread scheduling. Programs that rely on external sources of randomness, unsynchronized hardware events, or interaction with services outside the VM may still exhibit race conditions that Rewind cannot reproduce unless those effects are also controlled or mocked, leaving a gap in coverage for certain classes of concurrency bugs.

Check from here result card indicating 16 out of 16 schedules diverged after forking at step 3,221
After using Check from here at step 3,221 of the passing run, all 16 perturbed schedules ended differently, shown by 16 blue cellsfzakaria.com

This image visualizes the Check from here feature described in the first and third paragraphs, which tests many thread schedules to expose problematic interleavings.