Event Sourcing & Snapshot Lab (Interactive)
Fold an immutable event stream into a balance, then replay it with and without snapshots. Append deposits and withdrawals to an event-sourced account, time-travel any historical version, snapshot, and measure how O(history) rehydration cost changes.
Event Sourcing: Fold, Snapshot, Conflict
Current balance = reduce(events). Grow history to feel O(N) rehydration, then pin snapshots and race two writers.
Events Stored
2
append-only, never UPDATEd
Derived Balance
$150
fold(0, events)
Rehydration
1.6 ms
snapshot v0 + 2 delta events
Version Conflicts
0
optimistic concurrency catches
event_store — PRIMARY KEY (aggregate_id, version)
Aggregate acct_101 loaded at genesis; 2 events in the store.
A CRUD UPDATE destroys the past; the event log keeps every Klarna card authorization forever, so audit and time-travel debugging are free. The tax is O(N) rehydration — hit +500 legacy events with snapshots off and watch a read cost >20 ms, then snapshot every 50 and replay collapses to the delta. Version conflicts are caught by the database, not distributed locks.
How It Works Under the Hood
Event sourcing stores every state change as an immutable event and derives current state by folding the stream—the database becomes a cache over the log. You gain a perfect audit trail, time travel to any prior version, and replayable domain logic; you pay for it with unbounded streams whose rehydration cost grows linearly until snapshots truncate the replay, and with optimistic concurrency—writers must append (aggregate_id, version) and retry on conflict—because two threads reading version 41 both appending produce one rejected event.
Core Architectural Principles
- State = fold(events): balance recomputed from the log, never mutated in place, giving exact time travel.
- Rehydration cost is O(events since snapshot); periodic snapshots cap worst-case load time for hot aggregates.
- Expected-version tokens turn concurrent writers into append conflicts—one wins, one retries against fresh state.
Lead with the trade: "immutable history and time travel in exchange for eventual reads and snapshot housekeeping." Use the ledger as your example—append-only is already event sourcing—and mention optimistic concurrency on aggregate version plus snapshot cadence as the two production decisions you must defend.
Perfect auditability and replayable projections cost append-heavy storage, schema-versioned events, and snapshot maintenance.