Skip to main content
SDMastery
advanced8 min readUpdated 2026-06-08

CQRS

CQRS separates read and write models so each can be optimized independently — write to a normalized database, read from a denormalized projection.

Quick answer: CQRS

CQRS is covered here as a practical system design concept. CQRS separates read and write models so each can be optimized independently — write to a normalized database, read from a denormalized projection. Use it to understand the Architecture Patterns idea, where it appears in production systems, and how to discuss it clearly in interviews.

Focus on the problem being solved, the main design choice, the failure mode, and the tradeoff you would defend in front of a senior engineer. This page is part of the DosiBridge system design knowledge graph, so it links related concepts, interview problems, tradeoffs, and references instead of leaving the topic isolated.

Diagram showing the key components and data flow in a CQRS system design
High-level overview of CQRS
CQRS

CQRS (Command Query Responsibility Segregation) splits a system into two sides: commands that change state and queries that read state. Each side gets its own data model, optimized for its purpose. The write side uses a normalized model for consistency; the read side uses denormalized projections for fast queries. This pattern shines in systems where read and write workloads have vastly different characteristics — like an e-commerce site where product catalog reads outnumber order writes 1000:1.

AspectDetails
What it isA pattern that uses separate models for reading and writing data, allowing each to be optimized independently
When to useSystems with asymmetric read/write ratios, complex queries on write-heavy data, or when read and write scaling needs differ
When NOT to useSimple CRUD apps where reads and writes use the same model — CQRS adds complexity without benefit in these cases
Real-world exampleMicrosoft uses CQRS in Azure DevOps to serve billions of read queries from denormalized projections while writes go to a normalized event store
Interview tipPair CQRS with event sourcing — interviewers often ask about both together, and explaining eventual consistency between read/write models shows depth
Common mistakeExpecting immediate consistency between write and read sides — the read model is asynchronously updated, so queries may return stale data briefly
Key tradeoffScalability and query performance vs complexity and eventual consistency between the two models

Why This Matters

In traditional architectures, one model serves both reads and writes. This forces a compromise: normalize for write consistency or denormalize for read performance. CQRS eliminates this tradeoff. You can write to a normalized PostgreSQL database for ACID guarantees while serving reads from a denormalized Elasticsearch index or Redis cache. Each side scales independently. The read model is rebuilt from events, so you can create multiple projections optimized for different query patterns without touching the write side.

System architecture diagram for CQRS showing how services, databases, and caches connect
System architecture for CQRS

The Building Blocks

  • Command Model: Handles writes: validates business rules, persists state changes. Optimized for consistency — normalized, ACID-compliant. Rejects invalid mutations.
  • Query Model: Handles reads: serves precomputed, denormalized views. Optimized for speed — flat tables, materialized views, search indexes. No business logic.
  • Event Bus: Connects write to read side. After a command succeeds, an event is published. Read model projectors consume events and update denormalized views asynchronously.
  • Projectors: Event handlers that transform domain events into read model updates. One event can update multiple projections (e.g., order-placed updates inventory view AND revenue dashboard).
  • Eventual Consistency: The read model lags behind the write model by the event propagation delay (typically milliseconds). Queries may return slightly stale data.

Under the Hood

When a user places an order, the command handler validates the request (inventory check, payment authorization), writes to the orders table, and publishes an OrderPlaced event. The read-side projector receives the event and updates multiple views: the user's order history (denormalized with product names and images), the admin dashboard (aggregated revenue), and the inventory count (decremented).

Step-by-step diagram showing how CQRS processes a request from start to finish
How CQRS works step by step

The command model uses a normalized relational schema: separate orders, order_items, products, and users tables with foreign keys. The query model uses denormalized documents: a single order_summary collection with all data embedded. This means reads avoid JOIN queries entirely — a single document fetch returns everything the UI needs.

The key architectural decision is the projection mechanism. Synchronous projection (update read model in the same transaction as the write) provides strong consistency but couples the models. Asynchronous projection (via message queue) decouples them and allows independent scaling, but introduces eventual consistency. Most production CQRS systems use asynchronous projection with sub-second lag.

How Companies Actually Do This

Microsoft uses CQRS extensively in Azure DevOps. The write side stores work items in a normalized SQL database, while the read side serves queries from denormalized projections, handling billions of reads per day.

Comparison table for CQRS contrasting approaches, tradeoffs, and when to use each
Comparing key aspects of CQRS

Walmart implemented CQRS for their product catalog. Writes (price updates, inventory changes) go to a normalized database, while the shopping UI reads from Elasticsearch projections for sub-50ms query responses.

Netflix uses a CQRS-like pattern for their content catalog. Metadata writes go to a primary store, while multiple read-optimized projections serve different clients (TV, mobile, web) with different data shapes.

Common Pitfalls

  1. Applying CQRS to simple CRUD applications where the same model works for both reads and writes — the added complexity is not justified
  2. Not handling projection failures — if a projector crashes, the read model becomes stale. You need replay capability to rebuild projections from events
  3. Ignoring the eventual consistency gap — users who create an entity and immediately query for it may not see it if the projection hasn't caught up yet
Data flow diagram for CQRS showing how requests and responses move through the system
Data flow through CQRS

Interview Questions Worth Practicing

  1. When would you choose CQRS over a traditional CRUD architecture, and what complexity does it add?
  2. How do you handle the eventual consistency between write and read models in a CQRS system?
  3. How would you rebuild a corrupted read model projection from scratch?

The Tradeoffs

  • Query Performance vs Complexity: Denormalized read models eliminate JOINs and serve queries in O(1), but maintaining projectors and handling consistency adds significant system complexity.
  • Independent Scaling vs Operational Cost: Read and write sides can scale separately (e.g., 10 read replicas, 1 write database), but you now operate two data stores and a message bus.
  • Flexibility vs Consistency: Multiple read projections serve different query patterns perfectly, but all lag behind the write model, requiring careful UX design for the consistency gap.
Component diagram for CQRS showing each building block and its responsibility
Key components of CQRS

How to Explain This in an Interview

Here is how I would explain CQRS in a system design interview:

CQRS separates the system into command (write) and query (read) sides, each with its own optimized data model. I would use it when read and write patterns are fundamentally different — for example, an e-commerce site where writes are normalized for ACID (orders, inventory) but reads need denormalized documents (product pages with embedded reviews, ratings, pricing). The write side publishes events to a message queue, and read-side projectors build denormalized views. Each side scales independently. The main tradeoff is eventual consistency — after a write, the read model takes milliseconds to catch up. I handle this with optimistic UI updates on the client and always reading from the write model for just-created entities.

Interview preparation checklist for CQRS with key points to mention and mistakes to avoid
Interview tips for CQRS

Original DosiBridge notes for CQRS

This section is written specifically for this page, not copied from a general system-design checklist. The useful way to study CQRS is to connect the concept to a production service where growth exposes the first weak assumption in the original design. That framing changes the design discussion from definitions to operating choices.

What makes this topic distinct

  • Ownership Boundary: For CQRS, decide the ownership boundary before choosing tools; otherwise the design looks clean but fails when cqrs changes.
  • Blast Radius: For CQRS, decide the blast radius before choosing tools; otherwise the design looks clean but fails when cqrs changes.
  • Deployment Path: For CQRS, decide the deployment path before choosing tools; otherwise the design looks clean but fails when cqrs changes.
  • Runtime Coupling: For CQRS, decide the runtime coupling before choosing tools; otherwise the design looks clean but fails when cqrs changes.
  • Operational Handoff: For CQRS, decide the operational handoff before choosing tools; otherwise the design looks clean but fails when cqrs changes.

Production review question

If a team adopts CQRS, what observable signal proves it helped instead of only making the architecture diagram more fashionable?

Practical metric to track

Track cqrs health as a named dashboard or review item: combine one user-facing metric, one saturation metric, and one correctness metric. For CQRS, this keeps the discussion grounded in behavior that can be measured after deployment instead of generic advice that sounds good in an interview but never gets verified.