Introduction
CQRS: split the shape of writes from the shape of reads
In a classic CRUD service, one model and one database serve both commands (writes) and queries (reads). That works until read traffic is huge and shaped differently from writes: denormalized feeds, search projections, analytics dashboards — all fighting the same normalized write schema and the same connection pool.
CQRS (Command Query Responsibility Segregation) separates the command side (validate, decide, persist writes) from the query side (read models optimized for how you ask). They may use different models, storage engines, and scale paths. Consistency between them is usually eventual via events or projection pipelines.
Mechanism
- Client sends a command to the write model (rich domain validation, invariants).
- Write model persists (often relational, transactional) and emits events (preferably via outbox).
- Projectors update one or more read models (documents, caches, search indexes).
- Client queries read models with simple, fast lookups — not complex joins on the write DB.
CQRS is not required to mean Event Sourcing — but Event Sourcing pairs naturally (write model = append-only event log; read models = projections).
Worked example with numbers
Product catalog: write rate 50 product updates/s; read rate 20,000 browse QPS. Write model: normalized SKUs, prices, inventory reservations in Postgres. Read model: denormalized product cards in Elasticsearch/Redis.
- Without CQRS: every browse hits Postgres joins; primary struggles; cache helps but stampede and invalidation dominate ops.
- With CQRS: writes hit Postgres; events project to search/cache. Browse p99 served from read store. Staleness: price change may take 200–2000 ms to appear — product decision, not a bug, if bounded and monitored.
Flash sale edge: if oversell risk is unacceptable during projection lag, critical inventory checks stay on the write model (or use reservations on write path); only non-critical fields project async.
Why teams adopt it
- Independent scale of read vs write.
- Model fit — write for invariants; read for screens.
- Polyglot persistence where justified (search vs OLTP).
When NOT to use CQRS
- Balanced CRUD, one team, modest QPS — dual models are pure cost.
- You need strict read-your-writes everywhere without session stickiness or version tokens.
- Team cannot operate projection lag, rebuilds, and dual deployments.
- "CQRS" used as synonym for "two microservices" without different models — ceremony without benefit.
Failure / operability
- Projection lag — user updates profile, refresh shows old data. Detect: lag histogram; UX: wait for version or read-your-writes path.
- Broken projector — read model diverges forever. Detect: lag + checksum/sample reconcile jobs.
- Ordered projection violations — apply events out of order → corrupt document. Fix: per-aggregate sequencing / optimistic versioning.
- Rebuild cost — full reproject from events/hours of backlog. Practice rebuild runbooks.
Version-token read-your-writes, mechanically: the write side commits the change as aggregate version 42 and returns version=42 to the client. The client sends expected_version=42 on its next read. The read model stores the last projected version per aggregate; if it has only 41, the query layer either (a) waits/polls briefly until the projector catches up (costs read latency), (b) falls back to the write model for this one read (costs write-side load and a second code path), or (c) returns the stale view flagged as stale (costs UX honesty work) — a deliberate product choice per screen. This bounds the read-your-writes anomaly to the writer's own session instead of forcing global synchronous projection — the same mechanism DDIA teaches for reading your own writes under replication lag.
Decision defensibility
Why not only read replicas? Replicas share the same schema; they scale reads of the write shape, not denormalized query shapes. Why not only cache-aside? Cache helps hot keys but does not replace purpose-built query models for complex listings. CQRS when query shape and scale diverge hard from transactional writes.
Drill ladder
- Q: Is CQRS the same as microservices? A: No. CQRS is model segregation; can live in one deployable. Microservices are process boundaries.
- Q: Price update committed; UI shows old price for 3s. Bug? A: Often expected eventual consistency — unless SLA forbids it; then sync critical fields on write path.
- Q: First alert for a sick CQRS system? A: Projection lag / consumer lag on the read-model updater.
🤖 Don't fully get this? Learn it with Claude
Stuck on Introduction? Open Claude, copy a block below, and it'll teach you this exact concept — visually and interactively.
Build the mental picture, not memorization.
I just read a lesson on **Introduction** (System Design) and want to truly understand it. Explain Introduction from first principles using ONE vivid real-world analogy and a visual mental model — draw it as ASCII art or a clear step-by-step diagram — with a concrete example using real numbers. Then ask me one question to check I got the mental picture, and wait for my reply. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
Socratic — adapts to where you're stuck.
Teach me **Introduction** interactively. Ask me ONE guiding question at a time, wait for my answer, and adapt to my confusion — build the idea with me step by step instead of explaining it all at once. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
Active recall exposes what you missed.
Quiz me on **Introduction** with 5 questions, easy to tricky, ONE at a time. Tell me if each answer is right; at the end, explain clearly what I got wrong and why. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
Intuition + hook + flashcards for long-term memory.
Help me remember **Introduction** for the long term: give the one-sentence intuition, a memorable hook/mnemonic, a tiny worked example, and 3 active-recall flashcards (Q -> A). If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.