The Interleaving Explorer

Two agents. One database row. Six ways their operations can interleave, and one of them silently destroys committed work. This page lets you run every one of them.

My AI agents coordinate through a single SQLite file. One of the things they share is a set of context sections: named rows of markdown that any agent can read and update. An update is a full replace, so the row carries an integer version, and a well-behaved writer does a compare-and-swap: read the row, note its version, and submit the new content conditioned on that version being unchanged.

The catch is the writer that doesn't pass the version. A blind write. For a long time the system accepted those for compatibility, in a configuration called warn mode. The simulator below is a faithful small model of the real test that measured what warn mode costs, and it is the reason the production default is now enforce.

Writer B ยท CAS write

planread โ†’ write if version matches
read versionโ€“
resultโ€“

context_sections ยท one row

content"baseline content"
version1

What you just ran

The schedule is the whole game. Each writer's own program order is fixed (it must read before it writes), but which writer goes next at each step is picked by a seeded random number generator, exactly like the deterministic simulator in the real test suite. Same seed, same schedule, same outcome, every time. Step through seed 6 in warn mode: both writers read version 1, writer B's careful CAS write lands and commits, and then writer A's blind write replaces it. Both writers were told ok: true. B's committed work is gone, and B will never ask about it again, because as far as B knows, it succeeded. That is a lost update.

Now flip the toggle to enforce and run the identical schedule. The blind write is rejected. Nothing is lost. The interesting part is what the rejection leaves behind.

The receipt

This system's design rule is that nothing loses quietly. Every refused write, and every accepted blind overwrite in warn mode, files a durable conflict receipt in the same transaction as the decision itself. The warn-mode receipt even records a hash of the content it displaced, so there is a forensic trail pointing at exactly whose work was destroyed. Receipts are shown in violet above. Cause a conflict and read one.

All six interleavings

With two writers and two operations each, there are only six possible schedules. Small enough to enumerate. Click one to load it, then flip the mode toggle and watch the same schedule land differently.

Notice the structure. In warn mode the danger is concentrated in the two schedules where both writers read the same version and the CAS writer commits first. In two other schedules warn mode survives by luck: the blind write happens to land first, so the CAS writer's version check fails and it gets an honest rejection instead. Luck is doing the work a guarantee should do. In enforce mode all six schedules are safe, because the blind write is refused no matter where it lands.

The sweep that flipped a default

One seed is an anecdote. The real test suite runs a sweep of seeds and asks how often the lost update is actually reachable. Here are thirty seeds through this model, in warn mode:

In the real system's sweep, seventeen of thirty seeds reached the lost update. That number is what moved the default from warn to enforce: not a hunch about race conditions, but a measured statement that under concurrent writers, warn mode destroys committed work more often than not. The evidence seed is pinned in the repository and replays forever, so the bug that motivated the change can always be reproduced bit-for-bit.

Honest small print

This page schedules writers at read/write granularity. The real simulator schedules at every SQL statement, injects crashes and busy errors, and drives the actual production tool code against the actual schema on a simulated clock. The lost-update shape you explored here is the same one it found. And you do not need a distributed system for any of this to matter: this is five agents and one SQLite file on one laptop, and the interleaving still bit.

Self-contained page, no dependencies. View source: the simulation is ~120 lines of plain JavaScript and it is the tutorial. Part of a series on bridge-db, a SQLite-backed coordination server for a small fleet of AI agents.