Menu
Course/Data Management Patterns/CQRS (Command Query Responsibility Segregation)

CQRS (Command Query Responsibility Segregation)

Separate your read and write models: when CQRS helps, implementation strategies, eventual consistency between models, and common pitfalls.

18 min readHigh interview weight

What Is CQRS?

CQRS (Command Query Responsibility Segregation) is a pattern that separates the operations that read data (queries) from the operations that modify data (commands). Coined by Greg Young and inspired by Bertrand Meyer's Command-Query Separation principle, CQRS takes the idea further by using entirely separate models — and often separate data stores — for reads and writes.

In a traditional CRUD architecture, you have a single model that handles both reads and writes. This works fine for simple systems, but as complexity grows you start to see a painful tension: writes need strong consistency and transactional integrity, while reads need denormalized, fast-access projections optimized for specific UI views. CQRS resolves this tension by letting each side evolve independently.

Loading diagram...
CQRS separates the write path from the read path, each with its own optimized data store.

Commands vs Queries

AspectCommandQuery
IntentChange stateReturn data
Return valueTypically void or an IDReturns data (never changes state)
Examples`PlaceOrder`, `CancelShipment``GetOrderById`, `ListUserOrders`
ConsistencyStrong — uses transactionsEventual — reads from projection
ScalabilityWrite-optimized DBRead replicas, caches, search indexes

Implementation Levels

CQRS exists on a spectrum. You don't have to go all-in on day one:

  1. Simple CQRS — Single database, but separate command and query objects in code. Low overhead, good separation of concerns.
  2. Read replica CQRS — Same primary DB for writes, but queries go to a read replica. Easy to implement, the replica lag is the main trade-off.
  3. Full CQRS — Separate data stores for reads and writes. Write side uses a normalized relational DB; read side uses a denormalized store (e.g., MongoDB, Elasticsearch, Redis). Maximizes performance but adds operational complexity.
⚠️

Don't Over-Apply CQRS

CQRS adds significant complexity: separate models, eventual consistency, synchronization logic. Only apply it where the read/write performance needs or team scalability genuinely demands it. Simple CRUD applications get no benefit from full CQRS.

Eventual Consistency Between Read and Write

When you use separate read and write stores, the read model is eventually consistent. After a write command completes, it publishes an event (or the system uses CDC) to update the read store. Until that update propagates, queries may return stale data. This is the most common source of bugs in CQRS systems.

Loading diagram...
CQRS write-then-read flow with eventual consistency between models.

Real-World Usage

Amazon uses CQRS extensively in its order management systems. The write side processes orders with ACID guarantees, while read projections power the 'Your Orders' page — a denormalized view optimized for display. Stack Overflow uses a similar pattern where vote counts are written transactionally but cached/projected for fast tag-based queries. Microsoft documents CQRS as a core pattern for Azure microservices.

Common Pitfalls

  • Reading your own write — After a command, the UI queries immediately and gets stale data. Mitigate with optimistic UI updates or a short polling retry.
  • Projector lag — Under high load, the event bus or projector may fall behind. Monitor consumer lag like a production metric.
  • Schema coupling — If the read model schema is tightly coupled to events, changing event schemas becomes painful. Use event versioning.
  • Distributed transaction temptation — Developers sometimes try to make commands span multiple services atomically. This defeats the purpose — use Saga instead.
💡

Interview Tip

In interviews, CQRS is often brought up when you need to support very different read and write patterns — for example, a social media feed (complex aggregated reads, simple write path). Frame your answer around *why* you need it: read/write performance asymmetry, independent scaling, or supporting multiple read models. Always mention the eventual consistency trade-off proactively — it shows maturity.

📝

Knowledge Check

5 questions

Test your understanding of this lesson. Score 70% or higher to complete.

Ask about this lesson

Ask anything about CQRS (Command Query Responsibility Segregation)