Module 11 · Architectural patterns · Lesson 9 of 9
Event sourcing
Store every change as an immutable event and derive current state by replaying them. What you gain (complete history, audit, time travel, rebuildable projections), what you pay (event design, snapshots, schema evolution, querying).

The video walkthrough is part of Pro.
See what Pro includesWhy it matters
A bank does not store your balance; it stores every transaction and computes the balance. That is event sourcing, and it is the natural model for any domain where the history is the business: ledgers, inventory movements, order lifecycles, version control, collaborative documents. It gives a perfect audit trail and the ability to answer any question about the past, including questions nobody thought of yet. It also replaces a familiar storage model with a demanding one, and the interview question is whether you know when that trade is worth making.
The idea
In event sourcing, the system's source of truth is an append-only log of events, each an immutable fact about a change to an aggregate: OrderPlaced, ItemAdded, PaymentCaptured, OrderShipped. Current state is not stored as the primary record; it is derived by replaying the aggregate's events from the beginning (or from a snapshot). Writes append events; reads query projections built from them.
What it buys
- 1
Complete history and audit
Every change, who made it, when and why, is a first-class record. Compliance and debugging ask the log directly. - 2
Temporal queries
What was this account's state at 3 pm last Tuesday? Replay to that point. Why did the inventory go negative? Read the events. - 3
Rebuildable projections
Any read model can be created or corrected by replaying the log into it, which makes CQRS read models cheap to add and safe to fix. - 4
Natural event publishing
The events are the integration contract; no separate outbox is needed because the write is the event. - 5
Debuggability
Reproduce a bug by replaying the exact sequence that produced it.
What you pay
| Concern | Why it is hard | Mitigation |
|---|---|---|
| Event design | Events are permanent; a poorly named or over-granular event lives forever | Model from the business language; event storming; keep events about one aggregate |
| Replay cost | An aggregate with 100,000 events is slow to load | Snapshots: persist state every N events and replay only from the latest snapshot |
| Schema evolution | Old events must remain readable as the model changes | Versioned events; upcasters that transform old versions on read; never mutate stored events |
| Querying | You cannot SELECT across event streams | Projections for every query; the write side answers only by aggregate id |
| Eventual consistency | Read models lag the log | Same techniques as CQRS: versions, read-your-writes |
| Deleting data | Immutable log versus privacy regulations | Crypto-shredding: encrypt personal data per subject and delete the key; or tombstone events and rebuild projections |
| Team learning curve | Different from CRUD at every layer | Apply to one bounded context first |
Mechanics
Events for one aggregate form a stream keyed by aggregate id with a sequence number; appends use optimistic concurrency (expected version) so two concurrent commands on the same aggregate cannot both succeed. The event store is an append-only database (EventStoreDB, a Kafka topic with compaction turned off, a Postgres table with an index on stream id and version). Projections subscribe to the global log or to categories and maintain read models, tracking their position so they can resume. Snapshots are an optimisation, never the truth, and can be regenerated.
Event sourcing and CQRS
They are usually seen together because an event log is a poor read store, so read models are mandatory, and because the events are already there to feed them. They remain separate decisions: CQRS works over a conventional write model, and event sourcing can serve a single read model. Adopting both at once is the full pattern and the full cost.
Where it fits
Domains where the history is the product or the law: accounting and ledgers, inventory and stock movements, order and claim lifecycles, trading, versioned content, audit-heavy regulated workflows. Domains with collaborative or replayable state: document editing, games, workflow engines. It fits poorly for simple CRUD, reference data, high-volume telemetry (a time series store is better) and anywhere the team needs ad-hoc queries over current state more than history.