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.