Skip to content
Language:en Author:Laborci Gergely
event-driven

CQRS and the Read Model

Objectives

By the end of the lesson, you can explain what CQRS means, how it differs from event sourcing, what a read model is, and when it is worth using (and when not).

Why is it needed?

The needs of writing and reading often differ. For writing, keeping the rules is important (is an order valid); for reading, fast data fitted to the screen (a list that needs data from many sources). If the same model serves both, one side is forced to compromise.

What is CQRS?

According to Fowler, CQRS (that is, the separation of the responsibility of command and query) means using a different model to update information than the one used to read it. The two models are usually separate object models, often in different processes, sometimes with separate databases. The pattern is credited to Greg Young.

flowchart LR
  C["Modifying client"] --> W["Write side: rules"]
  W --> D[("Write state")]
  W -->|"changes"| P["Projector"]
  P --> R[("Read view")]
  Q["Reading client"] --> API["Query"]
  API --> R

Read model

A read model (materialised view) is a pre-assembled copy of data tailored to the needs of the consumer. A projector updates it from events or from changes on the write side. The reader queries a single source, with fewer synchronous dependencies than if it had to collect data from several services at request time.

The price is lag: after a write, the view may stay behind for a while, so the interface must be able to tell "being processed" from the final state. The view can be rebuilt if the source (events or the write state) is sufficient. The projector must be idempotent, since events may be repeated.

The difference between a cache and a read model

A cache reduces the cost of fetching; a read model is a designed, durable copy. A cache can be refreshed by time-based expiry or event-based invalidation. After invalidation, a slow query started earlier may write old data back, so version checking may be needed. A cache and a read model imply different contracts: a read model comes with a source, a lag and a rule for rebuilding.

When is it worth using, when not?

Fowler is sceptical: in his view CQRS adds risky complexity for most systems, many systems fit a simple CRUD model, and in most cases he has seen the pattern was not used well. In his view it helps in areas where the model is complex and the read and write loads differ, and it should be applied only to a bounded context of the system, not to the whole. If only the heavy queries cause trouble, a reporting database can be simpler.

By aspect

Aspect CQRS
Coupling The read model depends on the contract of the source's changes
Scaling The read and write sides can be scaled separately
Data management The view is a derived copy; the owner is the write side
Consistency The read side may lag (eventual consistency)
Cost Two models, projector, rebuild: significant

Common misconceptions

Statement Clarification
"CQRS needs event sourcing." Not necessarily.
"The read model is the source of truth." It is a derived copy; the owner is the write side.
"CQRS always speeds up the system." It helps only where the read and write needs really differ.
"CQRS must be applied to the whole system." According to Fowler, only to suitable bounded contexts.

In short

  • CQRS uses separate models for writing and reading.
  • A read model is a pre-assembled, lagging, rebuildable copy, updated by a projector.
  • CQRS is not event sourcing, and does not fit every system.
  • The freshness of the read model is part of the contract.

Review questions

  1. How does CQRS differ from event sourcing?
  2. What is a read model, and what is its price?
  3. When is a reporting database enough instead of full CQRS?

Learning resources

Prerequisites (2)

  • event-driven architecture
  • data owner

Teaches (2)

  • CQRS
  • read model