CQRS Pattern Explained: Command Query Responsibility Segregation
In traditional applications, the same model handles both writing and reading data. CQRS fundamentally changes this: it separates the write side from the read side.
The Core Concept
CQRS (Command Query Responsibility Segregation), as the name suggests, separates two responsibilities:
- Command — Modifies data, returns no result
- Query — Reads data, modifies nothing
User Request
↓
┌─────────────────────┐
│ Write Side │ ← Commands (CreateOrder, ProcessPayment)
│ (Command Model) │
│ - Business rules │
│ - Validation │
│ - Event emission │
└──────────┬──────────┘
│ Events
↓
┌─────────────────────┐
│ Read Side │ ← Queries (ListOrders, GetReport)
│ (Query Model) │
│ - Query-optimized │
│ - Denormalized data│
│ - Fast reads │
└─────────────────────┘
Why Use CQRS?
1. Independent Scaling
Read and write operations typically occur at vastly different scales. In an e-commerce site, the read/write ratio is usually 100:1. With CQRS, you can scale the read side independently.
2. Different Data Models
You can use normalized data (3NF) for writing and denormalized data (query-optimized) for reading.
Write model:
Order → OrderItem → Product → Category
Read model:
OrderView { orderId, customerName, items[], total, status }
3. Performance Optimization
Instead of complex JOINs on the read side, you use pre-built, denormalized views. Result: dramatic performance improvement.
4. Security
Since write and read interfaces are separate, different security policies can be applied to each.
CQRS + Event Sourcing
CQRS is at its most powerful when combined with Event Sourcing:
Command → Event Store → Events → Projection → Read Model
- User sends a command
- Command is processed and events are produced
- Events are written to the Event Store
- Projection process listens to events
- Read model (view tables) is updated
- Queries run against the read model
When to Use CQRS
✅ Good Fit
- High read/write ratio disparity
- Complex business rules on the write side
- Different query requirements
- Systems using Event Sourcing
- Report-heavy applications
❌ Poor Fit
- Simple CRUD applications
- Systems requiring immediate consistency
- Small teams with simple projects
Eventual Consistency
The most important trade-off of CQRS: there may be delayed consistency (eventual consistency) between the write and read models. A record may appear on the read side a few milliseconds/seconds after being written.
This is acceptable for most applications, but requires careful handling in some scenarios (e.g., bank account balances).
Practical Example: E-commerce
Write side:
CreateOrder { customerId, items[], address }
→ Validation: Is stock sufficient? Is customer active?
→ Event: OrderCreated { ... }
Read side:
GetOrders { customerId, page, filter }
→ Read from denormalized table
→ Result: [{ orderId, date, status, total }]
Reporting
CQRS shines brightest in reporting. You can create specialized materialized views for reports — without touching the core data model.
Conclusion
CQRS is a powerful architectural pattern, but not a silver bullet. When applied in the right context, it delivers performance, scalability, and flexibility. In the wrong place, it brings unnecessary complexity.
Learn CQRS and Event Sourcing hands-on through the Architect career path on LabLudus. The Software Architecture 3.0 book covers these topics in depth.