CQRS (Command Query Responsibility Segregation)
An architecture pattern that uses different models to update information than to read it. Martin Fowler credits Greg Young with first describing it. It is most often paired with event-sourcing; the two are independent patterns and neither requires the other.
The idea
- Commands change state. They should express a business task (“Book hotel room”), not a low-level data edit (“Set ReservationStatus to Reserved”). The write side carries validation, business rules and consistency.
- Queries never change data. They return data transfer objects (DTOs) shaped for the screen or API, with no domain logic.
- A traditional CRUD design uses one model for both. CQRS splits it because reads and writes often have different shapes, load and security needs (Microsoft Azure Architecture Center).
Levels of separation
| Level | What is separate | Cost |
|---|---|---|
| Separate models, one data store | Command and query code and object models; one database | Lowest; clearer code, little else changes |
| Separate data stores | Write store (for example relational) and read store (for example document database, search index or cache), possibly replicas | Needs synchronisation; reads become eventually consistent |
The usual synchronisation is for the write side to publish events that update the read model. Because a database and a message broker normally cannot share one transaction, Microsoft recommends the Transactional Outbox pattern (persist the state change and the event atomically) and idempotent read-model consumers that tolerate duplicate delivery.
Benefits (Microsoft’s list)
Independent scaling of reads and writes, schemas optimised per side, tighter security on who may write, cleaner separation of concerns, and simpler queries when a materialised view is stored.
Costs and cautions
- Complexity. Microsoft: it “can introduce significant complexity”, especially combined with event sourcing. O/RM scaffolding cannot generate CQRS code from a schema.
- Eventual consistency with separate stores: users can see stale data and may act on it.
- Messaging problems when messages are used: failures, duplicates, retries.
- Fowler’s warning: for most systems CQRS “adds risky complexity”; most CRUD-shaped systems should stay CRUD. Use it only inside specific bounded contexts (a Domain-Driven Design term), not across a whole system. If the problem is only demanding queries, a reporting database may be enough.
When it fits
Collaborative domains with many users changing the same data, task-based user interfaces over a complex domain model, and systems with a large read/write imbalance (Microsoft and Fowler agree on these).
With event sourcing
In the typical combination the write side loads an entity from its event stream, runs business rules, and appends new events; background projectors consume those events and update the read models that queries use. Details and trade-offs: event-sourcing.
Related
event-sourcing, incremental-development (start simple, add structure when it earns its place).