Skip to main content
Pattern

CQRS (Command Query Responsibility Segregation)

Problem

Your write model and read model have very different needs. Optimizing for one hurts the other.

Context

Writes are transactional and low-volume; reads are high-volume, denormalized, and could be served from a specialized store.

Solution

Split the model in two. The command side handles writes with strong consistency (usually a relational DB). The query side has one or more read models optimized for specific query patterns (denormalized cache, search index, materialized views). A pipeline (events, CDC) keeps read models updated from writes.

Trade-offs

  • Read models lag writes (eventual consistency)
  • Doubled operational surface: two schemas, two paths
  • Application code is more complex — different flow for reads vs writes
  • Read-after-write semantics require care (read from write model, or wait for lag)

Failure modes

  • Read model pipeline breaks; reads serve stale data forever
  • Write and read models diverge after schema evolution
  • Reader assumes strong consistency and sees stale data

When to use

  • Write model is normalized; reads need heavily denormalized shapes
  • Read volume 100× write volume
  • You need multiple specialized read models (search + graph + recommendations)

When NOT to use

  • Small applications where a single model works
  • Team can't handle eventual consistency
  • Reads are simple enough to serve from the write model