Chapter 24: Event Sourcing and CQRS
Event Sourcing
Instead of storing current state, store the sequence of events that led to current state.
// Traditional: store current state
account: {id: 1, balance: 850}
// Event sourcing: store all events
AccountCreated {id: 1, balance: 1000}
MoneyWithdrawn {id: 1, amount: 100}
MoneyDeposited {id: 1, amount: 50}
MoneyWithdrawn {id: 1, amount: 100}
// Current state = replay all events: 1000 - 100 + 50 - 100 = 850
Benefits
- Complete audit trail (every change recorded)
- Can rebuild state at any point in time
- Can derive new views/projections from same events
- Natural fit for event-driven architectures
Drawbacks
- Querying current state requires replaying events (use snapshots)
- Schema evolution of events is complex
- Eventually consistent read models
CQRS (Command Query Responsibility Segregation)
Traditional: same model for reads and writes
App ──read/write──► Single Database
CQRS: separate models optimized for each
Commands (writes) ──► Write Model (normalized, event store)
│ events
▼
Event Bus (Kafka)
│
▼
Queries (reads) ◄── Read Model (denormalized, optimized for queries)
Use CQRS when: read and write patterns are very different (e.g., complex writes but simple reads, or vice versa). Don't use for simple CRUD apps.
Key Takeaways
- Event sourcing: store events, derive state. Full audit trail.
- CQRS: separate read/write models for different optimization
- Both add complexity — use only when the problem demands it
- Event sourcing + CQRS + Kafka = powerful but complex architecture
- Simple CRUD? Just use PostgreSQL. Don't over-engineer.