Glossary Architecture Patterns

CQRS

Command Query Responsibility Segregation separates the write model (commands) from the read model (queries) so each can be optimized independently.

The Problem with a Single Model

A normalized relational schema is optimal for writes: foreign keys enforce integrity, updates touch one row, constraints prevent invalid state. That same schema is often terrible for reads: a dashboard page might join 8 tables, aggregate across millions of rows, and filter on columns without indexes. The write model and the read model have fundamentally different shapes. Forcing both through the same schema means the write schema is denormalized for reads (causing update anomalies) or the read queries are expensive because the schema is normalized for writes.

CQRS resolves this by making the separation explicit: the system has a write side (commands that mutate state) and a read side (queries that return data), each with its own model optimized for its purpose.

How It Works

On the write side, commands represent intent: PlaceOrder, CancelSubscription, UpdateShippingAddress. The command handler validates, applies business rules, and writes to the write store. The write store is typically normalized and strongly consistent.

On the read side, queries are handled by read models: denormalized, pre-aggregated projections optimized for specific views. An order list view might be a flat table with all the fields needed for that page, pre-joined from orders, customers, and products. No joins at query time. Reads are fast because the work was done at write time.

The read models are kept up to date by consuming events or change notifications from the write side. This is where CQRS and event sourcing converge naturally: the write side publishes events, the read-side projections subscribe and update their denormalized stores.

CQRS vs Read Replicas

A read replica is a copy of the write database with the same schema. It offloads read traffic but does not solve the schema mismatch problem. The read queries on a replica are still joining normalized tables. True CQRS maintains a separately modeled read store, often with a completely different schema (or even a different database technology: a relational write store and an Elasticsearch read store for full-text search).

Consistency Window

The gap between writing a command and having the read model reflect it is the consistency window. In event-driven CQRS, this is typically 10-500ms depending on queue depth and projection processing speed. Applications must be designed around this: if a user places an order and immediately navigates to "my orders," the new order may not appear yet. Common mitigations include: returning the new resource directly in the command response (so the UI can optimistically render it), using causality tokens to wait for a specific event to propagate, or accepting the eventual consistency as a product decision.

Operational Cost

CQRS doubles the surface area: two data stores, two codepaths, two sets of schemas to migrate. A write-side schema change often requires a corresponding read-model rebuild. Debugging a data discrepancy requires tracing through the event pipeline. Teams without prior experience frequently underestimate this cost. CQRS is not a default architecture. It is appropriate for domains with genuinely complex query requirements that diverge significantly from the write model.

Scaling the Read and Write Sides Independently

One concrete production benefit: the write side and the read side can be scaled independently. If your system receives 100 writes per second but 50,000 reads per second, the read store can scale horizontally (additional read replicas, Elasticsearch cluster nodes) without affecting the write store. The write store remains small and optimized for transactional throughput. This separation is impossible when both operations share a single schema: adding read replicas helps with read volume but they still run the expensive normalized queries that CQRS's read model eliminates.

Technology Choices by Side

The write store does not need to be the same technology as the read store. A common pattern: PostgreSQL as the write store (ACID transactions, strong consistency, relational integrity) paired with Elasticsearch as the read store (full-text search, complex aggregations, sub-50ms query latency on millions of records). The write side publishes domain events; a consumer indexes those events into Elasticsearch in near-real time. The application queries Elasticsearch for reads and PostgreSQL only for writes that require strong consistency guarantees.

Interview Tip

The distinguishing question: "How is CQRS different from just adding a read replica?" Candidates who can articulate the schema difference and the projection concept are operating at depth. The L6-level addition: discuss the consistency window and how you handle read-your-own-writes in an eventually consistent read model, the independent scaling benefit, and the technology choice freedom it enables. Mentioning that CQRS is not worth the complexity for simple CRUD-heavy domains demonstrates judgment, which interviewers value as much as pattern knowledge.