skip to content

What is the difference between CQS (Command-Query Separation) and CQRS (Command Query Responsibility Segregation)?

level: seniorimportance: must knowfreq 62%

answer

  1. CQS = method level; CQRS = model/architecture level
  2. Meyer → Greg Young generalized it
  3. CQRS ≠ event sourcing, ≠ two databases
  4. async read model ⇒ eventual consistency, read-your-own-writes
  5. apply per bounded context, not system-wide

basics

~20 s

CQS is a method-level style rule: a method either mutates or returns, never both. CQRS is an architecture pattern: separate read and write models — often separate objects, services, or even databases — for the whole system or a bounded context.

solid answer

~50 s

**CQS** (Meyer) applies inside a class: each method is a command or a query. It costs nothing, needs no infrastructure, and is a sensible default everywhere. **CQRS** (named by Greg Young, generalizing CQS) applies the same split one level up: the objects that change state and the objects that answer questions are *different types*, with different models. Writes go through a command model enforcing invariants; reads use denormalized, query-shaped read models. Once the read side is a separate store, it is usually updated asynchronously, so it becomes **eventually consistent**, and you must handle stale reads and read-your-own-writes. Common confusions to correct: CQRS does not require event sourcing, does not require two databases (separate read/write models in one schema is still CQRS), and is not free — it adds a synchronization path, more code, and consistency-lag UX problems. Adopt it for asymmetric read/write scale or radically different read shapes, not by default.

go deeper

for a junior

State that CQS is about individual methods and CQRS is about separating the read and write parts of a system, and that CQRS is much bigger and rarely needed on a small app.

for a middle

Add the structure — command side enforcing rules, read models shaped for screens — and name the trade-off: keeping the read side in sync, often asynchronously.

for a senior

Cover the lineage from Meyer to Young, insist CQRS is independent of event sourcing and doesn't imply two databases, explain eventual consistency and read-your-own-writes with concrete mitigations, and give clear adoption criteria.

for a principal

Frame it as a bounded-context-scoped decision with real operational cost: projection rebuild and replay tooling, schema evolution of read models, idempotent projectors, monitoring of projection lag, and the organizational readiness required — plus a default answer of 'no' for CRUD-shaped contexts.

## The one-line distinction | | **CQS** | **CQRS** | |---|---|---| | Scope | a single **method** | a **model / service / subsystem** | | Coined by | Bertrand Meyer (~1988, *OOSC*) | Greg Young (~2010), building on Meyer and on Udi Dahan's work | | Rule | a method either mutates state or returns a value, never both | the type that handles writes and the type that handles reads are different, with different models | | Cost | ~zero; a naming and discipline convention | significant: extra code, synchronization, possible extra store, eventual consistency | | Default? | yes, use it everywhere | no, use it where justified | | Consistency impact | none | usually introduces eventual consistency on the read side | **CQRS is CQS applied at the object/architecture level instead of the method level.** Young has said as much: he started from Meyer's rule and pushed the separation up to whole objects. --- ## CQS in one paragraph Every operation is a **command** (changes observable state, returns nothing meaningful — `order.cancel()`) or a **query** (returns a value, changes nothing — `order.total()`). This makes reads safe to repeat, cache, log, assert on, and parallelize, and confines mutation to a small, visible set of calls. Accepted exceptions exist where read and write must be atomic (`pop()`, compare-and-swap). --- ## CQRS in detail ### The structure - **Command side (write model)** — receives intent-shaped commands (`PlaceOrder`, `CancelOrder`), loads the consistency boundary (in DDD terms, an *aggregate* — a cluster of objects with an invariant to protect), validates business rules, and persists changes. It is normalized and optimized for enforcing invariants. It typically returns nothing or just an acknowledgement/id. - **Query side (read model)** — a separate set of types (often plain DTOs / projections) built to match what screens and reports need. Denormalized, pre-joined, indexed for the query shapes actually used. It never enforces business rules because it never writes. - **The synchronizer** — the mechanism that keeps the read side current: writing to both in the same transaction (synchronous CQRS), a database view or materialized view, change-data-capture, or (most commonly discussed) **domain events** published by the write side and consumed by projectors that update read models. ### The consistency consequence If the read model is updated in the same transaction, CQRS is strongly consistent and the only cost is code duplication. If it is updated asynchronously, the read side lags by milliseconds to seconds, which produces the two problems every CQRS system must answer: 1. **Stale reads.** A dashboard shows numbers slightly behind reality — usually fine. 2. **Read-your-own-writes.** A user submits a form and is redirected to a list that doesn't contain their new item yet — usually *not* fine. Standard mitigations: return enough data from the command to render the next screen optimistically; have the client poll or subscribe until the projection catches up; version-stamp the write and have the read wait for that version; or route that particular read to the write model. ### What CQRS is *not* - **Not event sourcing.** Event sourcing (persisting state as an append-only log of events and replaying it) pairs *well* with CQRS because a log naturally feeds projections, but each works alone. You can do CQRS over plain relational tables, and you can event-source a system with a single model. - **Not "two databases".** Two different classes hitting the same schema with different queries is already CQRS. Separate stores are an optimization, not the definition. - **Not a whole-system mandate.** CQRS is applied per **bounded context**. A typical system uses it in the one or two contexts where reads and writes genuinely diverge and stays with a single model everywhere else. - **Not an alternative to CQS.** They compose: inside a CQRS write model you still write CQS-clean methods. ### When it earns its cost - Read and write loads differ by orders of magnitude (read-heavy product catalogs, feeds, analytics) and you want to scale or replicate them independently. - The read shapes are radically different from the write shape — many joins, aggregations, or search — so one model serves neither well. - Reads must be served from a specialized store (search index, graph, column store, cache). - Complex domain invariants on writes coexist with dumb, high-volume reads; the models pull in incompatible directions. - Audit/temporal requirements push you to event sourcing anyway. ### When it does not - CRUD-shaped domains with modest scale — a single model plus a few read-optimized queries is simpler and strictly better. - Teams unable to absorb the operational burden of a synchronization pipeline, replay tooling, and consistency-lag UX. - "Because it's modern" — Young himself has repeatedly warned that most systems applying CQRS should not have. --- ## How to answer this in an interview Give the one-line distinction (method-level style rule vs architectural model separation), note the lineage (CQRS was named after and generalizes CQS), then immediately show you know the cost: eventual consistency and read-your-own-writes, the decoupling from event sourcing, and the fact that it applies per bounded context. Being able to say **when not to use CQRS** is what separates a senior answer from a memorized one.

  • Does CQRS require event sourcing?
    No. They are frequently paired because an append-only event log is a natural feed for building read-model projections, but CQRS only requires separate read and write models — which you can build over ordinary tables, views, or change-data-capture. Conversely you can event-source a system that has a single model. Conflating them is the most common CQRS misconception.
  • Your read model lags by a second and users complain that their newly created item isn't in the list. What are your options?
    Render the new item optimistically from data returned by the command; have the client wait on a version/sequence number stamped by the write and poll or subscribe until the projection reaches it; route that one read to the write model; or make the write synchronous with the projection for this specific view. Each trades a bit of the decoupling back for read-your-own-writes.
  • Is separating read and write methods on the same class already CQRS?
    That is CQS, not CQRS. CQRS begins when the read path uses a *different model* — different types shaped for querying — rather than the same domain objects with more getters.

CQS is a rule about how you write each individual sentence — a sentence either states a fact or gives an order. CQRS is a rule about how you organize the whole book: reference material lives in an index built for lookup, while the narrative that changes the story lives in the chapters. Building an index is genuinely useful, but somebody has to keep it up to date, and right after you edit a chapter the index is briefly wrong.

context