CQRS Read-Model Projection¶
Read/write-split read model — instantiates Access-Optimized Redundant Representation
Splits the write model from the read model so each is shaped for its job — the write side stays normalized and validating, while one or more read models are denormalized per query and updated after the fact.
CQRS Read-Model Projection separates the model you write from the model(s) you read — Command Query Responsibility Segregation. The write side keeps the normalized schema and the invariants; the read side is one or more separately-stored, denormalized projections, each shaped for a specific query and each updated after the write commits. Its defining move is architectural rather than local: it is not "one faster copy" but a standing split in which the command side holds all write authority and the query side is a fan of derived, eventually-consistent read models — one per access path. Adding a new way to read the data means adding a new read model, not contorting the write schema to serve every screen.
Example¶
A project-management app has to satisfy one write rule — a task can't be assigned inside an archived project — and three very different reads: a Kanban board grouped by column, a "My Work" list grouped by assignee, and a Gantt-style timeline. Under CQRS the write model stays normalized and enforces the rule; each of the three views is its own read model, precomputed in exactly the shape its screen wants, so each renders in a single read with no cross-table assembly. When a task command commits, the change propagates to the three read models, which converge a moment later (eventually consistent, on the order of ≈100 ms here). A fourth screen next quarter is a fourth read model — the write side never has to change to accommodate it.
How it works¶
- Commands own the truth. Writes go only to the command model, which validates and holds authority; nothing writes to a read model directly.
- Read models are per-query and derived. Each access path gets its own denormalized projection; reads never touch the write model.
- Update after the fact. A change on the write side propagates to the read models asynchronously, so they trail the write within a bounded lag.
Tuning parameters¶
- Number of read models — more models make more queries cheap but enlarge the surface that must be kept in sync.
- Consistency lag budget — how stale a read model may be after a write. Tighter budgets cost more propagation machinery.
- Propagation transport — events, change-data-capture, or an outbox carrying writes to the read side; sets ordering and delivery guarantees.
- Read-model autonomy — how independently each model's schema can evolve from the write schema and from its siblings.
When it helps, and when it misleads¶
Its strength shows when read and write workloads genuinely diverge — few, invariant-heavy writes against many differently-shaped, high-volume reads. Splitting them lets each be optimized without compromise, and new read shapes become additive. It misleads when imposed on a plain CRUD domain, where the segregation adds synchronization complexity that buys nothing, and it surprises users who expect read-your-writes and instead see a read model that hasn't caught up.[1] The classic misuse is adopting CQRS as architecture fashion on a domain that never needed it. The discipline is to reach for it only where the read/write shapes actually pull apart, and to make the consistency lag visible to the interface rather than pretending the read side is instantaneous.
How it implements the components¶
CQRS Read-Model Projection realizes the read/write-separation side of the archetype — the standing split and its consistency contract:
read_path_contract— each read model is a query-shaped contract readers bind to, decoupled from the write schema so reads and writes can evolve apart.write_authority_rule— the command side is the sole writer; every read model is strictly derived and is never treated as authoritative.freshness_and_staleness_bound— read models are eventually consistent, so the allowable lag behind the write side is an explicit part of the design.
It does not carry the changes from write side to read side (a transport like Change-Data-Capture Propagation or Transactional Outbox Projection does), build a single view by folding a log (that's Event-Sourced Projection), or detect when a read model has drifted (that's Checksum and Sample Reconciliation).
Related¶
- Instantiates: Access-Optimized Redundant Representation — a fan of redundant read models, each subordinate to one authoritative write model.
- Consumes: Transactional Outbox Projection or Change-Data-Capture Propagation to propagate committed writes to the read models.
- Sibling mechanisms: Event-Sourced Projection · Read-Model Version Gate · Materialized View · Transactional Outbox Projection · Change-Data-Capture Propagation
Notes¶
Read-your-writes is the sharp edge. Right after a user submits a change, their next read may hit a read model that hasn't updated yet, so the edit appears to vanish. Mitigations — serving that user from the write side briefly, or gating their read on a version token (Read-Model Version Gate) — have to be designed in, because the naive path silently shows people stale versions of their own actions.
References¶
[1] Eventual consistency — the guarantee that derived copies will converge to the source given no new writes, but may lag it at any given moment. It is the consistency model CQRS read models live under, and naming the acceptable lag explicitly is what separates a deliberate design from an accidental race. ↩