The Lost Update
Two sessions read the same note at 10:00. Each adds a paragraph. Each saves. With a plain file, the second save silently replaces the first, and one session's paragraph is gone without anyone being told. This is the lost update, the oldest bug in shared storage, and a soul vault with many writers (the WebUI, coding sessions on several Macs, scheduled jobs) meets it constantly.
Soul Vault's answer is optimistic concurrency: compare-and-swap. A writer says not only what the note should become but also what it believes the note is now. If that belief is out of date, the write is refused.
A Revision Is a Hash
The belief is expressed as a revision, and in Soul Vault a revision is simply the SHA-256 of the note's bytes. Every read returns it. Every write must hand one back as expected_revision. That choice has a nice property: a revision is not an opaque counter the store invents, it is something any reader can compute from the bytes it holds. Two readers holding identical bytes hold the same revision, whatever store served them.
Inside the root's write_batch, under the vault's lock, every change is checked against the current bytes:
- An update to a note that does not exist:
note_not_found. - An update whose expected revision differs from the hash of the current bytes:
revision_conflict, with the current revision attached indetailand a cause that ends with the instruction: "reread and rebase". - A create (a note that must not exist yet) over a note that does exist:
already_exists, again with the current revision.
Only when every change in the batch passes does the template call the child's _apply. A batch is all or nothing: one stale revision refuses the whole batch.
The Second Life Problem
Creates have a subtler race. Session A lists a folder, sees that memory/2026-11-12-x.md does not exist, and goes off to compose it. Meanwhile session B creates that note, and session C deletes it. When A finally writes, the note is absent again, so a plain "must not exist" check passes, and A's create lands on top of a history it never saw.
Contract v5 closed that with the absent token. When a caller finds a note absent, it can ask absent_token(note) and keep the answer, then pass it as the expected revision of its create. In the Delta store the token encodes the sequence number of that path's last recorded event (absent:s<seq>). If the note was created and deleted in between, the sequence moved, the token no longer matches, and the create is refused: "it was created and deleted in between ... read again and decide again". From a Mac that cannot reach the canonical store, the token is deliberately one that names no state of it, so a create carrying it later is a conflict and its caller reads again.
Proved Under Load
Before the cutover, a load drill ran against a scratch copy of the real vault: 141 writes acknowledged and none missing from history, and a burst of 12 concurrent writes to one note that landed exactly 1 and refused the other 11 as conflicts. That second number is the whole point of this lesson. Eleven writers were told the truth ("someone got there first; reread") instead of eleven paragraphs disappearing.