The idea
Instead of UPDATE account SET balance = 70, append MoneyWithdrawn {amount: 30}. The balance is a fold over all events. Nothing is ever overwritten.
Key mechanics
- Streams per aggregate (
release-123), with optimistic concurrency on the expected version. - Snapshots every N events so loading stays fast.
- Upcasting or versioned events, because old events live forever and schemas evolve.
- It almost always comes with CQRS, since you can't query an event log efficiently.
- Audit and history are core requirements (finance, compliance, content versioning)
- You need 'what did this look like on date X?'
- Business insight from behaviour over time is valuable
- Simple CRUD domains
- The team is new to event-driven design
- You need frequent ad-hoc queries on current state without projections
Trade-offs
- ✅ A perfect audit trail, time travel, debugging by replay, and new projections from history.
- ❌ Event schema evolution is hard and permanent.
- ❌ GDPR-style deletion needs patterns like crypto-shredding.
- ❌ A steep learning curve, and it's easy to over-apply.
Content versioning in a CMS is a lighter cousin of this: every save creates a new version you can compare and roll back to. Full event sourcing goes further and makes the change log the primary store.
Sources & further learning
Videos, courses, docs and books I recommend for this topic.
Related topics
CQRS (Command Query Responsibility Segregation)
Use one model to change data (commands) and a different, optimised model to read it (queries) — often kept in sync by events.
Event-Driven Architecture
Services announce facts ("EntryPublished") and others react asynchronously — decoupling producers from consumers in time, space and knowledge.
Saga Pattern
Keep data consistent across services without distributed transactions — a sequence of local transactions, each with a compensating action if a later step fails.