The Audit-Proof Ledger

An auditor asks three questions a mutable database cannot answer: what was the balance last March, is this history real, and did your logic still hold after last week’s deploy? The answer is to stop storing the balance and start storing the events — every validated fact, in order, forever. Built from zero: commands versus events (intent versus recorded fact), the deterministic state machine whose replay is byte-for-byte reproducible, why the same events always yield the same balances, CQRS read models rebuilt per consumer, and the systems engineering that makes it fast (append-only files, memory-mapping, snapshots to bound replay) and reliable (a Raft-replicated event log where the leader appends and followers replay). The signature exhibit replays the same twelve-event log twice for identical balances, then corrupts one historical event and watches the divergence surface at exactly that event — computed live from a real reducer.

Concept · Systems. The source ↗

A free, interactive, animated visual explainer of The Audit-Proof Ledger — built to be understood, not skimmed.

Questions

What is event sourcing?
Event sourcing is a way of storing state as an ordered log of the things that happened, rather than as a single mutable snapshot of the current state. Martin Fowler defines its core as “Capture all changes to an application state as a sequence of events.” Instead of a wallet row you overwrite on every transaction, you append an immutable event — “deposited $50,” “withdrew $20” — and the current balance is a value you compute by replaying those events from the beginning. The events are the source of truth; the balance is derived. Because nothing is ever overwritten, you keep a complete, replayable history: “We can discard the application state completely and rebuild it by re-running the events from the event log on an empty application.” That property is what makes the ledger auditable — every number on it can be traced back to the exact sequence of facts that produced it.
What is the difference between a command and an event?
A command is a request to do something — “transfer $50” — that may still be rejected; an event is a fact that already happened — “transferred $50” — that can never be un-happened. The command carries intent and is validated against the current state (is there enough balance? is the account frozen?); only if it passes does the system record one or more events. This split matters for reproducibility: events are the validated results, so replaying them never re-runs the validation or re-makes a decision that could now go differently. A command might fail; a stored event is settled. Event sourcing stores the events, not the commands, which is why replaying the log always reproduces the same state.
Why does event sourcing need a deterministic state machine?
Because the whole guarantee — that replaying the same events always produces the same state — only holds if applying an event is a pure function of the current state and the event, with no hidden inputs. The moment the apply logic reads something outside the event — the wall clock, a random number, a value fetched from another service — two replays of the identical log can diverge, and the ledger is no longer reproducible. So event-sourced systems push all non-determinism into the events themselves: if a decision depends on the current time, the time is captured in the event when it is first recorded, and replay reads it from there. The reducer that folds events into state must be deterministic, or the audit guarantee evaporates silently.
What is CQRS and how does it relate to event sourcing?
CQRS — Command Query Responsibility Segregation — is the idea, in Martin Fowler’s words, that “you can use a different model to update information than the model you use to read information.” The write side accepts commands and appends events; the read side builds whatever query-optimized shape a consumer needs by subscribing to those events — a current-balance table, a monthly-statement view, a fraud-analytics feed — each rebuilt independently and thrown away or recomputed at will. It pairs naturally with event sourcing because the event log is exactly the stream those read models consume. But it is not free: Fowler cautions that “for most systems CQRS adds risky complexity,” and that it “should only be used on specific portions of a system and not the system as a whole.”
How do snapshots make event sourcing fast?
By bounding how much of the log a reader has to replay. If a wallet has ten million events and computing its balance means folding all ten million from the beginning, a cold read is unacceptably slow. A snapshot is a periodically saved copy of the derived state at a known event position — say, the balance as of event 9,990,000 — so a reader loads the snapshot and replays only the handful of events since it. The trade-off is a real dial: snapshot often and cold reads are cheap but you spend more on writing snapshots; snapshot rarely and writes are cheap but the replay tail grows. The events remain the source of truth — a snapshot is only a cache of a computation you could always redo from the log.

Related explainers