Cloud Parts

CQRS

Command Query Responsibility Segregation: one model handles changes and enforces the rules, separate read models answer queries, and the read side catches up from the changes.

1 technology on this page ↓
Live model
What you’re watchingCommands go to the write model, which rejects a few that break the rules and records an event for each change. The projector reads the events at its own pace and updates the read model, which answers the much busier stream of queries, sometimes with data a moment old.

How it works

It starts from Bertrand Meyer’s command-query separation: a method either changes state and returns nothing (a command) or returns a result without side effects (a query). CQRS, credited to Greg Young and Udi Dahan, applies that split to whole models. A CustomerService with both MakeCustomerPreferred and GetCustomer becomes a write service and a read service. On the write side, commands are named for business tasks (“book room”, not “set status to reserved”); the write model validates them, enforces the rules, usually on DDD aggregates, and may reject them. On the read side there is no business logic: queries return data transfer objects from views shaped for each screen, often denormalised so a page needs no joins. In the simplest form both models share one database. In the fuller form the read side has its own store, and the write side publishes an event whenever it changes something; a projector consumes the events and updates the views. That makes the read side eventually consistent: for a moment after a change, a query can return stale data. A transactional outbox saves the change and the event atomically, and an idempotent projector tolerates duplicates. The read store doesn’t have to be a database: views are disposable copies that can be rebuilt from the source, so a projector can write each one as a file to object storage behind a CDN, and reads then never touch a database, at the cost of more lag and a rewrite of every file a change affects. CQRS is often paired with event sourcing, where the stored events are the write model, but neither needs the other.

Think of it as

A library’s returns desk and its catalogue. You hand books in at the desk, where staff check them against the rules. A clerk updates the public catalogue afterwards, laid out for searching rather than for checking in. For a few minutes after a return, the catalogue may still say “on loan”.

Reach for it when

  • Reads and writes need very different shapes, or reads outnumber writes by orders of magnitude and must scale on their own
  • Collaborative domains where many users change the same data and commands should capture intent
  • A complex domain already modeled with DDD aggregates and a task-based user interface
  • One bounded context that needs it, not the whole system

Think twice when

  • The domain or business rules are simple and a CRUD interface does the job
  • Users must always see their own change immediately and you can’t design around stale views
  • Only a few slow reports hurt; a separate reporting database is a smaller step

A real example

A hotel site handles 2,000 searches and 20 bookings a minute. A BookRoom command goes to the write model, which checks that the room is free that night and saves the booking in a normalised schema. It publishes RoomBooked, and a projector removes the room from a denormalised free_rooms_by_city_and_date table that search reads with one indexed lookup. For about a second after a booking, search can still show the room as free. If a second guest tries to book it in that window, the write model rejects the command, so the stale view costs a retry, not a double booking.

More on cqrs

Narrower ideas that build on this one.

Technologies

Specific products, and what each does differently.

CQS, CQRS and event sourcing#

Three ideas that often appear together and are easy to blur. Each works without the others.

IdeaApplies toThe splitOrigin
Command-query separation (CQS)Methods of one objectA method changes state or returns a value, not bothCoined by Bertrand Meyer in Object-Oriented Software Construction
CQRSModels and servicesOne model for commands, separate models for queriesDescribed by Greg Young and Udi Dahan in the late 2000s
Event sourcingStorageStore the sequence of changes and rebuild state by replaying it, instead of storing only the current stateCredited, with CQRS, to Young, Dahan and those they inspired; when paired, the event store is the write model

Keeping the read side up to date#

The split is simple; most of the work is in how changes reach the read models.

One database, two models

simplest

Write and read models are separate code over the same store; the database itself carries changes from one to the other. No lag, but reads and writes can’t scale or change storage independently.

Separate read store

eventually consistent

The write side publishes an event per change and a projector updates a store built for queries, which can even be a different kind of database, such as a document store beside a relational write store. Reads scale out with replicas; views lag behind writes.

Outbox and idempotent projectors

no lost events

A database write and a message publish can’t usually share one transaction, so save the event in an outbox table in the same transaction as the change, and make the projector safe to run twice on the same event.

Rebuild by replay

with event sourcing

When the events are the source of truth, a new or broken read model can be rebuilt by replaying the history from the start.

Why most systems don’t need it#

Martin Fowler’s 2011 note is the standard caution. Many systems fit a CRUD mental model and should be built that way. CQRS is “a significant mental leap for all concerned”, and most cases Fowler had run into had not gone well, with CQRS a significant drag on productivity and a source of risk, even in capable teams. Fowler advises using it only in specific bounded contexts, not across a whole system.

Its benefits come in two forms: a few complex domains get easier to model, and systems with very different read and write loads can scale and optimise each side separately. If only some demanding queries hurt, Fowler suggests a reporting database instead: the main system still serves most reads, and only the heavy ones move.

In code · ts

type RoomBooked = { type: "RoomBooked"; roomId: string; date: string; guest: string };

// Write side: enforces the rule and records what happened
const bookings = new Map<string, string>();   // "room|date" -> guest
const outbox: RoomBooked[] = [];              // stands in for an outbox table or a broker

function bookRoom(cmd: { roomId: string; date: string; guest: string }): void {
  const key = `${cmd.roomId}|${cmd.date}`;
  if (bookings.has(key)) throw new Error(`room ${cmd.roomId} is taken on ${cmd.date}`);
  bookings.set(key, cmd.guest);
  outbox.push({ type: "RoomBooked", ...cmd });
}

// Read side: a view shaped for the search screen, updated only from events
const freeRooms = new Map([["2026-11-03", new Set(["101", "102"])]]);

function project(e: RoomBooked): void {
  freeRooms.get(e.date)?.delete(e.roomId);
}
function searchFree(date: string): string[] {   // a query: no rules, no writes
  return [...(freeRooms.get(date) ?? [])];
}

bookRoom({ roomId: "101", date: "2026-11-03", guest: "Ada" });
console.log(searchFree("2026-11-03"));   // ["101", "102"]: stale until the projector runs
outbox.splice(0).forEach(project);
console.log(searchFree("2026-11-03"));   // ["102"]
try { bookRoom({ roomId: "101", date: "2026-11-03", guest: "Bob" }); }
catch (e) { console.log((e as Error).message); }   // room 101 is taken on 2026-11-03

Often confused with

Where it came from1988–2014

The idea starts with Bertrand Meyer, who coined command-query separation in Object-Oriented Software Construction, first published in 1988, as part of Meyer’s work on the Eiffel language. Methods fall into two sharply separated kinds: queries that return a result and change nothing observable, and commands that change state and return nothing. The payoff is confidence: queries can be called anywhere, in any order, without surprises.

In the late 2000s, people in the domain-driven design community began applying the same split to architecture. Udi Dahan published a training course applying CQRS with service-oriented design in 2008 and wrote “Clarified CQRS” in December 2009, arguing from collaboration and staleness: data shown to a user may already have been changed by someone else, so reads might as well come from a separate store kept roughly in sync. Greg Young’s CQRS Documents (2010) explained that it was long discussed as “CQS at a higher level” before being recognised as a different pattern, and set out task-based commands, events and denormalised read models.

Martin Fowler’s bliki entry of July 2011 brought the name to a wider audience along with a warning that most systems don’t need it. By 2014 Eric Evans described CQRS and event sourcing as “quite mainstream options” for the architecture of a DDD system, and cloud architecture guides, such as Microsoft’s, now document it as a standard pattern with the same caveats.

Why it’s built this way

Split the model, not just the methods
Using one conceptual model for both updates and display tends to produce a model that does neither well, especially in complex domains.
Commands named for tasks, not field edits
A data-oriented interface has only four verbs (create, read, update, delete), and conversations with domain experts rarely do. Commands like “deactivate inventory item” capture what the user meant.
Accept stale reads
In a collaborative system the data on a user’s screen can be out of date the moment it is shown. Most systems can tolerate eventual consistency on the query side, while the command side checks the rules against current data.
Normalised writes, denormalised reads
The command side wants data near third normal form for safe transactions; the query side wants it flattened to avoid joins, and handles a far larger share of the traffic.

Timeline

  1. 1988

    Bertrand Meyer’s Object-Oriented Software Construction introduces command-query separation

  2. 2008

    Udi Dahan’s training course applies CQRS with service-oriented design

  3. 2009

    Dahan’s “Clarified CQRS” separates the pattern from event sourcing

  4. 2010

    Greg Young’s CQRS Documents set out the architecture

  5. 2011

    Martin Fowler’s bliki entry warns that most systems don’t need it

  6. 2014

    Eric Evans calls CQRS and event sourcing mainstream options for DDD systems

Sources7

Improve this page on GitHub