Basic CQRS (no event sourcing)
Who uses it: Team starting with CQRS without full event sourcing
Write model: a relational database with normalized tables
Read model: a denormalized view in the same or different store
Events emitted after each command for cross-side sync
Read model can be rebuilt from the write model
Lower complexity than event sourcing, still benefits from split
Why this works: Basic CQRS is the cleanest entry point — the diagram has a normal database on each side, with events bridging them. You get independent scaling and read optimization without committing to event sourcing's complexity.
CQRS with event sourcing
Who uses it: Team where the event log should be the source of truth
Write model is the event store itself — append-only events
State is derived by replaying events
Read models built by projecting events on subscribe
New read models can be added by replaying from event 0
Audit and time-travel come for free
Why this works: CQRS + event sourcing is the strongest form — the diagram makes the event store the system of record, and read models become fully derivable from it. Adding a new view is just writing a new projector.
Multiple read models
Who uses it: Team with several distinct query patterns
One write model, many specialized read models
Read 1: Elasticsearch for full-text search
Read 2: Redis for low-latency lookups
Read 3: Postgres for complex reporting joins
Each projector consumes the same event stream independently
Why this works: Multiple read models are the strongest justification for CQRS — the diagram shows the same write side feeding multiple projections, each optimized for a different access pattern, which a single CRUD model can't do efficiently.
CQRS within microservices
Who uses it: Team using CQRS as a per-service pattern
Each microservice picks CQRS or CRUD per its needs
Cross-service events flow through a shared bus
Service A's events feed Service B's read model
Saga patterns coordinate cross-service writes
API gateway hides the split from clients
Why this works: CQRS pairs naturally with microservices — the diagram shows it applied per-service rather than system-wide, so each service chooses CQRS only where it wins, and cross-service eventing handles coordination.