Skip to main content

Command Query Responsibility Segregation (CQRS)

CQRS separates the command (write) model from the query (read) model so each is optimized and scaled independently. It excels in complex, read-diverse domains but adds eventual-consistency complexity.

Type
Data
When to Use
Divergent Read Write Models, Independent Read Scaling, Complex Domain

Command Query Responsibility Segregation (CQRS) splits an application into two models: one that mutates state (commands) and one that reads state (queries). Instead of a single model serving both, each side is shaped for its purpose. The write side enforces business rules; the read side is denormalized for fast, query-specific access. It generalizes the older Command-Query Separation principle from method design to whole subsystems.

How It Works

Commands express intent ("place order") and are validated against the write model, which may be a normalized relational schema or an event-sourced aggregate. After a write, the change is propagated to one or more read models — materialized views, denormalized tables, search indexes, or caches — each tailored to a specific query. Queries hit these read stores directly and never touch the write model.

Propagation is often asynchronous via events, which makes the read side eventually consistent. CQRS does not require event sourcing, separate databases, or async messaging, though it is frequently combined with them. The minimal form is simply distinct read and write models in the same database.

When to Use It

Apply CQRS when read and write workloads diverge sharply: a domain with complex write-side invariants but many varied, high-volume read shapes; systems that must scale reads independently of writes; or collaborative domains with task-based UIs. It is especially powerful when paired with event sourcing for auditability.

Trade-offs

CQRS adds significant complexity: two models to keep in sync, eventual consistency to reason about, and more moving parts to operate. It is over-engineering for simple CRUD applications, where a single model is clearer and cheaper. Read models can lag writes, so the UI must handle stale reads gracefully. Rebuilding read models and handling duplicate or out-of-order events demands discipline. Adopt CQRS selectively, per bounded context, not system-wide by default.

Related Patterns

CQRS pairs naturally with event-sourcing (the write log) and materialized-view (the read stores), and propagation typically rides an event-driven-architecture.

Example

An order-management service writes commands to an event-sourced aggregate. Each event updates several read models: a denormalized orders table for the customer's history, an Elasticsearch index for support search, and a metrics roll-up for operations. Reads are fast and purpose-built, while the write model guarantees that order invariants hold.