What is CQRS (Command Query Responsibility Segregation)?
Learn what CQRS is, how it separates read and write models, its relation to event sourcing, and its consistency trade-offs.
Expected Interview Answer
CQRS is an architectural pattern that splits a system into two separate models β one for writes (commands) and one for reads (queries) β instead of using a single model for both, so each side can be optimized, scaled, and evolved independently.
In a traditional CRUD design, the same data model and often the same database serves both writes and reads, which forces compromises: a schema normalized for safe writes is rarely the shape that makes reads fast. CQRS separates commands, which mutate state and enforce business rules, from queries, which return read-optimized projections, sometimes backed by an entirely different data store such as a denormalized document store or search index. The write side stays strict and transactional, while the read side can be scaled horizontally, cached aggressively, or rebuilt from events without touching the write path. CQRS is frequently paired with event sourcing, where the write side appends events and the read side subscribes to them to build projections, but the two patterns are independent and CQRS can be used with a conventional database on both sides too.
- Lets the read and write models be scaled and optimized independently
- Enables read-optimized denormalized projections without complicating the write model
- Reduces write-side contention because reads no longer compete for the same schema or locks
- Pairs naturally with event sourcing for full audit trails and rebuildable read models
AI Mentor Explanation
CQRS is like a cricket ground having a strict official scorer who records every ball against the laws of the game, completely separate from the giant stadium screen that only displays a simplified, fan-friendly summary of runs and wickets. The scorerβs ledger (the write model) is the single source of truth and is slow and careful, while the big screen (the read model) is rebuilt constantly from that ledger to be fast and easy to glance at. Fans never write to the big screen directly, and the official scorer never worries about how pretty the display looks. Keeping these two responsibilities apart is exactly what CQRS does for a software systemβs writes and reads.
Step-by-Step Explanation
Step 1
Client issues a command
A write request (e.g., "PlaceOrder") is sent to the command handler, which validates business rules and mutates the write model.
Step 2
Write model persists the change
The command handler commits the change transactionally, often emitting a domain event describing what happened.
Step 3
Read model is updated
A projection builder consumes the change (synchronously or via events) and updates a denormalized read store optimized for queries.
Step 4
Client issues a query
Read requests go to the query side, which serves fast, pre-shaped data directly from the read store without touching write-side logic.
What Interviewer Expects
- Clearly separates the concept of commands (mutate) from queries (read) as two distinct models
- Mentions that read and write sides can use different data stores and scale independently
- Distinguishes CQRS from event sourcing (related but independent patterns)
- Raises eventual consistency between write and read models as a real trade-off
Common Mistakes
- Claiming CQRS requires event sourcing (it does not β they are separable patterns)
- Applying CQRS to simple CRUD systems where the added complexity is not justified
- Ignoring the eventual consistency lag between write model and read projections
- Confusing CQRS with simply adding a read replica of the same schema
Best Answer (HR Friendly)
βCQRS means splitting how you write data from how you read it, using two separate models. The system that handles writes focuses on validating and enforcing rules correctly, while the system that handles reads is built purely for fast, simple lookups. It adds complexity, so it is best used for parts of a system where reads and writes have very different scaling or shape needs.β
Code Example
async function placeOrderCommand(cmd) {
const order = validateAndCreateOrder(cmd) // write-model rules
await writeDb.orders.insert(order)
// publish event for the read side to consume asynchronously
await eventBus.publish("OrderPlaced", {
orderId: order.id,
userId: order.userId,
total: order.total,
placedAt: order.placedAt,
})
return order.id
}
// separate read-side projection handler, denormalized for fast queries
eventBus.subscribe("OrderPlaced", async (event) => {
await readDb.orderSummaries.upsert({
orderId: event.orderId,
userName: await lookupUserName(event.userId), // pre-joined for speed
total: event.total,
placedAt: event.placedAt,
})
})
async function getOrderSummary(orderId) {
return readDb.orderSummaries.findOne({ orderId }) // fast, no joins
}Follow-up Questions
- How does CQRS relate to and differ from event sourcing?
- How do you handle a client that reads its own write immediately after a command, given eventual consistency?
- When would you NOT recommend CQRS for a system?
- How would you version and rebuild a read projection if its schema needs to change?
MCQ Practice
1. What does CQRS primarily separate?
CQRS splits the write (command) model from the read (query) model so each can be optimized independently.
2. Is CQRS the same thing as event sourcing?
CQRS and event sourcing are complementary but distinct patterns; CQRS can be implemented without event sourcing.
3. What is a common trade-off introduced by CQRS?
Because the read model is updated asynchronously from the write model in most CQRS implementations, reads can briefly lag behind writes.
Flash Cards
What is CQRS? β A pattern that separates the write model (commands) from the read model (queries) in a system.
Does CQRS require event sourcing? β No β they are independent patterns often paired together, but CQRS can use conventional databases on both sides.
Main trade-off of CQRS? β Read projections are often eventually consistent with the write model, and the pattern adds architectural complexity.
When is CQRS most useful? β When read and write workloads have very different scaling, shape, or performance needs.