CQRS
Separating the read model from the write model so each can be optimized independently. Writes go through commands to a normalized store; reads come from optimized projections. Often paired with event sourcing.
- Read-heavy domains with many query shapes.
- Event-sourced systems where projections are natural.
- Simple CRUD where one model suffices.
- When eventual consistency between reads/writes is unacceptable.
Definition
Command Query Responsibility Segregation splits mutation (commands) from queries. The write side enforces invariants; the read side serves denormalized, query-optimized views, updated asynchronously from the write side.
Why it exists
One model rarely serves both strict writes and fast varied reads. CQRS lets you scale and shape reads (many projections, caches) without burdening the write path with query optimization.
How it works
Commands validate and persist to the write store, then emit events/updates that flow to read models. Reads query projections directly, often eventually consistent. The two sides can use different stores (e.g. Postgres write, Elasticsearch read).
Scaling limits
Eventual consistency between write and read models. More infrastructure (projections, sync). Complexity rises; debugging requires tracing across models. Only worth it for complex or high-scale domains.
Cost shape
More stores and sync pipelines = more infra and ops. Blow-ups: projection lag, duplicate sync infrastructure.
Alternatives
- Single model — Simpler, but reads and writes fight for the same shape.
- Materialized view — Read optimization without full CQRS, DB-managed.
Failure modes
- Projection lag causing stale reads.
- Write/read model divergence.
- Operational complexity obscuring bugs.