Event Sourcing & CQRS · CQRS and Projections
CQRS Explained
Separate the write model from read models — with or without event sourcing.
CQRS (Command Query Responsibility Segregation) separates the write model (commands, invariants, aggregates) from read models optimized for queries (denormalized tables, search indexes, caches). It pairs naturally with event sourcing — events update read models — but can be used with a normal database too. The trade-off is eventual consistency between writes and reads, plus more moving parts.
Single model vs CQRS
| Criterion | Single model | CQRS |
|---|---|---|
| Query performance | Joins on normalized tables | Precomputed read models |
| Write model complexity | Shared with reads | Focused on invariants |
| Consistency | Immediate | Eventual for read models |
| Scaling | Together | Independently |
| Complexity | Low | Higher |
Write side: POST /orders → PlaceOrder command → Order aggregate → OrderPlaced event (event store)
Read side: projector consumes OrderPlaced → upserts order_summaries (SQL) + search index + customer_stats
Queries: GET /customers/42/orders → SELECT from order_summaries (no joins)
Common pitfalls
- Applying CQRS to simple CRUD screens.
- Ignoring eventual consistency in the UI.
- One giant read model instead of per-use-case models.
Key points
- Separate writes and reads
- Read models per use case
- Eventual consistency is the price
Further reading: Martin Fowler: CQRS
Practice questions
Does CQRS require event sourcing?
Answer
No. You can keep a normal write database and build separate read models via CDC, outbox events or synchronous updates; event sourcing is a common but optional pairing.
What's the main trade-off of CQRS read models?
Answer
They're eventually consistent: a read right after a write may not yet reflect it.
Open in the app to mark lessons complete, take notes and track your progress.