Event sourcing stores what happened instead of what is. Every state change appends to an immutable log as a domain event — OrderPlaced, PaymentCaptured — and current state is computed by replay. Tables holding latest values become derived, disposable views.
It is a persistence decision, local to one component. A monolith can event-source a single aggregate without any broker; event-driven architecture answers a different question — how components talk — and varies independently.
How It Works
- A command rehydrates its aggregate by replay (or snapshot plus tail), validates invariants, and appends new events under an expected-version concurrency check.
- Projections subscribe to the log and maintain read-optimized views, each rebuildable from event zero.
- Events never change. Schemas evolve through versioned event types and upcasters that translate old events during replay.
- Corrections append compensating events, ledger-style.
Failure Modes
- Internal events published as integration contracts couple external consumers to the domain model; refactoring an aggregate then breaks unknown downstream systems.
- Projections lag the log: a user who saves and reloads sees stale data without read-your-own-writes handling.
- Neglected versioning surfaces late — a replay halts on events no current code can deserialize.
- Storage and replay time grow without bound; the first projection rebuild attempted during an incident takes days.
Verification
- A projection rebuild from event zero runs regularly and completes inside its time budget, matching the live view; the replay deserializes every historical event version.
- Projection lag stays below its threshold; an alert fires on the oldest unprocessed event’s age.
- A crypto-shredding drill confirms personal data is unrecoverable from log, snapshots, and projections.
Variants and Related Tactics
- Event-driven architecture moves events between components; event sourcing persists them within one. Translate internal events into a published language at the boundary instead of exposing the log.
- CQRS is the natural companion: writes append, reads project.
- A plain audit log is cheaper when history serves compliance only and never derives state.
- Change data capture retrofits an event stream onto a CRUD store — row deltas without domain intent.
References
- Event Sourcing — Martin Fowler (2005)
- Versioning in an Event Sourced System — Greg Young (Leanpub, 2017)
- Implementing Domain-Driven Design, Appendix A — Vaughn Vernon (Addison-Wesley, 2013)
- Designing Data-Intensive Applications, ch. 11 — Martin Kleppmann (O’Reilly, 2017)