CQRS (Command Query Responsibility Segregation)
CQRS separates write operations (commands) from read operations (queries) into distinct models, allowing each to be optimized independently.
CQRS = a restaurant with separate 'order' and 'pickup' counters. Writing your order (command) and reading the menu board (query) happen at totally different windows optimized for different speeds.
In a simple CQRS setup, the command side writes to a normalized, strongly-consistent store (e.g., Postgres). The query side maintains one or more denormalized read models (e.g., Elasticsearch, Redis, a materialized view) built by reacting to events emitted by the command side. This solves the N+1 query problem and allows reads to scale independently. The trade-off is eventual consistency on the read side and the operational burden of keeping projections in sync.
CQRS becomes powerful when combined with event sourcing but is valuable independently. The read projection is rebuilt by replaying the event stream — this means you can add new read models retroactively without touching the command side. The hardest operational problem is projection catch-up: when you deploy a new projection, it must replay potentially millions of events, which takes time during which it is stale. Checkpoint snapshotting (storing a periodic aggregate snapshot so replay starts from the snapshot, not event 0) is the standard mitigation. A subtle bug: read models that include business logic create divergence — projections should be pure transformations of events, not re-implementations of domain rules.
I reach for CQRS when query access patterns are fundamentally different from the write model — for example, a financial system where debits/credits are appended but users need real-time balance across multiple currencies. The command side uses an append-only ledger; the read side uses a projection that aggregates balances per account per currency. Event sourcing on the command side gives us a free audit trail and the ability to replay projections when regulatory requirements change.
Applying CQRS to every service. For simple CRUD, a single model with read replicas is sufficient. CQRS adds significant complexity (eventual consistency, projection management, operational overhead) and should only be introduced when the read/write impedance mismatch is causing real pain.