CQRS Visualized
Learn CQRS with some diagrams
Most explanations of CQRS drown you in definitions. This one shows you the one
moment that makes it click: you save something, read it back immediately, and it
isn't there yet. That gap is the whole pattern. Let's earn it.
(You’ll find a working demo in C# /.NET at the end)
The problem
In a normal CRUD app, one model does two jobs: it enforces business rules on writes
and gets reshaped for every screen on reads. That’s fine until the jobs fight —
your entity bloats, your queries grow joins, and you can’t make reads faster without
risking writes.
CQRS (Command Query Responsibility Segregation) splits them in two:
The write side owns correctness. The read side owns speed. Domain events
keep them in sync. Reads never touch the write model's joins — they hit pre-shaped
views, so they're trivial and scale on their own.
Two things people get wrong: CQRS is not two databases (that's an option, not
the definition), and adding a message bus is not CQRS. The defining move is
separate read and write models.
The choice that defines everything: when does the read side catch up?
This is where it gets interesting. You decide when the projection runs.
Synchronous — run it inline, before the write returns. Reads are always fresh:
Asynchronous — drop the event on a queue and return instantly; a background
worker projects it later. Fast writes, but the read side serves stale data
until it catches up:
That red window is eventual consistency — the cost of CQRS at scale.
Here's what GET /tickets returns over time after closing a ticket at t=0:
The trade-off, in one table
So when do you actually use CQRS?
Use it when reads and writes genuinely diverge: different shapes, wildly
different load (reads ≫ writes), or a complex domain where query concerns pollute
your business rules. Think product catalogs, social feeds, dashboards, ledgers.
Skip it for simple symmetric CRUD — it’s pure overhead. And if you can’t
tolerate stale reads and can’t design the UX around them, stay synchronous or
stay CRUD.
The mature move isn’t “use CQRS.” It’s knowing that the write side is your truth,
the read side is a rebuildable cache, and choosing how fresh that cache must be —
on purpose.
Demo: https://github.com/kaldren/SystemDesignLab/tree/main/01-CQRS
This repository follows an AI-first approach and is designed to evolve into a platform for learning, experimentation, and technical content creation. The goal is to leverage AI to streamline the development of Proof of Concepts (POCs) while automatically generating supporting artifacts such as documentation, architectural notes, and blog content.






