Event sourcing
Store every state change as an immutable event; the current state is a projection of replaying those events.
Event sourcing flips the data model: instead of storing current state and updating it, you store every change as an event. Current state is reconstructed by replaying the events.
The shift
Traditional:
UPDATE accounts SET balance = 150 WHERE id = 42;You lose history. You know the balance is 150. You don't know how.
Event sourcing:
INSERT INTO events: account_opened(id=42, balance=0)
INSERT INTO events: deposited(id=42, amount=200)
INSERT INTO events: withdrew(id=42, amount=50)
To get the balance, replay the events: 0 + 200 - 50 = 150.
What you gain
- Full audit trail. Every change is preserved, attributable, timestamped.
- Time travel. Replay events to see state at any point in history.
- Multiple read models. Project the same events into different views.
- Easy temporal queries. "What was the balance on March 15?"
- Debugging in production. Replay the bug-causing events in a sandbox.
What you pay
- Complexity. Every developer needs to learn the model.
- Schema migrations. Renaming a field means handling old AND new event versions forever.
- Snapshots. Replaying 10 million events to compute current state is slow. You need snapshots, which add bookkeeping.
- Eventual consistency. Projections lag the event store. UIs have to handle "you just wrote this but it isn't in the read model yet."
- Operational maturity. Backups, recovery, event-store sizing are all new problems.
When to use it
- Regulatory or audit needs. Banking, healthcare, anything with compliance.
- Genuine temporal queries. "What did our inventory look like last Tuesday?"
- Complex domains with many derived views. Multiple read models from one source.
When NOT to
- CRUD apps. A blog is not event-sourced.
- You picked it for resume-driven development.
- Team doesn't have someone who has done it before. The learning curve is real.
CQRS goes with it
Event sourcing pairs naturally with Command Query Responsibility Segregation: commands write events, queries read from projections. The write model and read model are separate.
You can do CQRS without event sourcing. You usually don't do event sourcing without CQRS.
My rule
Don't event-source by default. Pick it deliberately for domains that need audit, time travel, or multiple read models. Use Postgres or Kafka as the event store, start simple, snapshot every 100-1000 events.
Learn more
- ArticleMartin Fowler: Event Sourcingmartinfowler.com
- Talk
- ArticleDesigning Data-Intensive Applications, ch 11Martin Kleppmann