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.

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

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.

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.

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