Reference
Software Architecture
What Is CQRS?
A canonical explanation of CQRS: treating reads and writes as two different problems with two different models, why that split exists, and when it is worth the cost.

Almost every system starts with one model for everything. A single Order object is loaded from the database, mutated when the customer changes something, and read back when a page needs to display it. The same shape serves the write and the read. It is the obvious design, and for a long time it is the right one.
The strain shows up later. The shape that is convenient to write — normalized, validated, guarding invariants — is rarely the shape that is convenient to read. A dashboard wants a wide, denormalized row joining six tables. The write side wants those six tables kept apart so each stays consistent. One model is now being pulled in two directions, and it serves neither well.
CQRS is the decision to stop pulling.
Definition
- CQRS (Command Query Responsibility Segregation)
An architectural pattern that separates the model used to change state (commands) from the model used to read state (queries). Instead of one representation serving both, each side gets a model shaped for its own job. The two are kept in sync, but they are no longer the same code, and often not the same storage.
The mental model: reads and writes are different problems
The core insight is almost embarrassingly simple once you see it. Writing and reading are not two operations on one thing — they are two different problems.
Writes are about protecting invariants. Can this order be cancelled? Is this seat still available? Does this transfer leave the account solvent? A write model exists to say no at the right moments. It is small, normalized, and jealous about consistency.
Reads are about answering questions fast, in whatever shape the caller needs. A read model exists to say yes, here it is — pre-joined, denormalized, indexed for the exact query, often cached. It never needs to enforce a rule, because it never changes anything.
Forcing both jobs through one model means every query pays for the write side’s guarantees, and every write fights the read side’s convenience. CQRS lets each side be honest about what it is for.
How it works
Commands and queries travel different paths. A command (CancelOrder) goes to the write model, which validates it against the current state and, if allowed, persists the change. A query (GetOrderSummary) goes to a read model — a separate table, view, cache, or even a separate database — that was built to answer exactly that question.
The read model does not maintain itself. Something has to propagate changes from the write side to the read side. That “something” is usually events: the write model emits a fact when state changes, and a projection updates the read model in response. This is why CQRS and events are so often mentioned together — the same fact that describes a write is exactly what a read model needs to stay current.
How it relates to event sourcing
CQRS is frequently paired with event sourcing, and the two reinforce each other so naturally that many people conflate them. They are separate ideas.
Event sourcing is about how the write side stores truth: as an append-only log of events rather than mutable rows. CQRS is about keeping reads and writes as different models. You can do CQRS with two ordinary SQL tables and no event log at all. You can do event sourcing with a single model and never split your reads.
But together they click. If your write side is already an event log, building read models is just folding those events into whatever shape a query wants — and you can build as many specialized read models as you have questions, all from the same source of truth. Event sourcing gives you the stream; CQRS gives you the freedom to project it many ways.
When to use it
CQRS earns its keep when the read and write workloads genuinely diverge:
- Read and write loads scale differently. A system read a thousand times per write can scale its read models independently — replicas, caches, denormalized views — without touching the write path.
- The read shape fights the write shape. When your queries need data assembled from many aggregates, a purpose-built read model beats increasingly baroque joins.
- You need many views of the same data. Reporting, search, and the app UI can each own a projection tuned for its needs.
- It already pairs with event sourcing. If your writes are events, CQRS is the natural way to read them.
When not to use it
The most common mistake is applying CQRS to an entire system by reflex. It is a pattern for the parts of a domain where reads and writes actually pull apart — not a house style. Most applications have a handful of such hotspots and a long tail of ordinary tables that a single model serves perfectly.
Key takeaways
- CQRS separates the write model from the read model because changing state and querying state are different problems with different constraints.
- The write side protects invariants; the read side answers questions fast, in whatever shape the caller needs.
- Read models are kept current by propagating changes — usually as events — from the write side.
- It is distinct from event sourcing but composes with it beautifully; either can be used alone.
- Apply it selectively, to the hotspots where one model is genuinely in the way. For ordinary CRUD, one model is still the honest answer.
The question CQRS answers is not “how do I store my data?” but “should the thing that enforces my rules be the same thing that answers my questions?” When the answer is no, splitting them is the whole point.
// continue exploring