CQRS and Eventual Consistency
At 12:25 every weekday, two very different things hit DabbaGo's orders table at once. Thousands of customers are placing orders, which needs careful checks: is the kitchen full, is the cut-off past, did payment succeed? Meanwhile, hundreds of kitchen and owner dashboards are running heavy queries: orders per kitchen, per area, per dish. The writes and the reads want different shapes of data, and they are fighting over the same tables.
The rule
Changing data and asking about data can use separate models.
CQRS stands for Command Query Responsibility Segregation. It splits the system into two sides:
- Commands change state:
PlaceOrder,CancelOrder,MarkReady. The write model checks the rules and saves the change. It is shaped for correctness, not for reporting. - Queries answer questions: "how many orders does Kitchen 14 have today?" The read model stores data already shaped for those questions, such as a small table of totals per kitchen. Queries never change anything.
How does the read model stay up to date? Usually the write side publishes an event after each change, such as OrderPlaced { kitchen: 14, dishes: 2 }, and a handler updates the read model.
That gap between the write and the read update creates eventual consistency: for a short time, the read model is behind. If no new changes arrive, it catches up and agrees with the write side. For a few seconds after an order is placed, Kitchen 14's dashboard might still show 41 orders instead of 42.
CQRS is not free. It adds a second model, events and handlers, and a delay users may notice. Many systems never need it. It pays off when reads and writes have very different shapes or loads.
The shortcut
For each screen or check, ask: "What happens if this number is a few seconds old?"
- Nothing bad → it can read from an eventually consistent read model.
- Something bad, such as money lost or promises broken → it must read from the write side, or be enforced inside the command.
Separate the command
PlaceOrderchecks the cut-off time and kitchen capacity against the write model and saves the order.
The trap is using the read model to make decisions that must be exact. Eventually consistent data is for showing, not for guarding limits.
Drills
Answer fast — trust the rule.
In CQRS, which of these is a command?
A customer places an order and the owner's dashboard shows the new total three seconds later. What is this called?
Where should DabbaGo check that a kitchen has capacity for one more tiffin?
When is CQRS most likely to be worth its extra complexity?
Remember
- CQRS separates commands, which change data, from queries, which only read it.
- Shortcut: "what happens if this number is a few seconds old?"
- Trap: guarding limits or money with an eventually consistent read model.
