Event sourcing
Storing state as an append-only log of domain events; the current state is derived by replaying them. It gives a full audit history and enables temporal queries and rebuilds. The tradeoff is complexity and event schema evolution.
- Domains needing full audit history and temporal queries.
- When you want to add new read models later from old data.
- Simple CRUD where current state is all you need.
- Teams without the discipline for schema evolution.
Definition
Instead of storing mutable current state, you append immutable events to a log; projections rebuild read models and current state by folding the events. The event store is the source of truth.
Why it exists
Mutable state loses history. An event log captures every change, enabling audit, replay, new projections from old data, and decoupling writes from reads. Natural for domains like accounting and banking.
How it works
Commands produce events appended to a stream (per aggregate). Projections consume the stream to build read models (CQRS). Snapshots avoid replaying the whole history. Schema evolution uses upcasters to migrate old events.
Scaling limits
Replaying long histories is slow (use snapshots). Event schema evolution is hard once events are stored. Eventually-consistent projections lag the write model. Versioning and migrations are non-trivial.
Cost shape
Storage grows with event volume (append-only). Projections add compute and storage. Blow-ups: huge streams and many projections.
Alternatives
- CRUD with audit log — Simpler, but history is a side channel, not the source of truth.
- CQRS without events — Separate read/write models using current state.
Failure modes
- Breaking event schema changes.
- Projection lag causing stale reads.
- Snapshot corruption.