data

CQRS & Event Sourcing

Separate the write model (commands) from the read model (queries) — each shaped for its workload. Optionally store every state change as an immutable event (event sourcing).

CQRS — Command Query Responsibility Segregation — splits a system's write side from its read side, on the observation that the two have fundamentally different needs. Writes care about validation, business rules, and consistency; reads care about fast, flexible querying in whatever shape the UI needs. Forcing one model to serve both leads to compromises: a normalised schema great for writes makes complex reads slow, while a denormalised one optimised for reads is awkward to keep consistent on write. CQRS lets each side use a model and even a data store tuned for its job.

A bank statement versus your balance: the balance (read model) is convenient, but it's derived from the immutable ledger of transactions (the event log) that you can always replay.

Key Concepts

1
In its basic form, commands (state-changing operations) go through one model that enforces invariants and persists changes, while queries go through a separate read model — often a denormalised, pre-joined projection kept in a store optimised for fast reads. The read side is typically updated asynchronously from the write side via events, which means it is eventually consistent: a moment after a write, the read model catches up. Event sourcing is a frequent and powerful companion: instead of storing only the current state, you store every state change as an immutable, append-only sequence of events, and current state is derived by replaying them. That gives you a complete audit log, the ability to reconstruct state at any past point in time, and a natural event stream from which to build any number of read projections — but it adds real complexity around event schema evolution, replay performance (mitigated by snapshots), and the mental shift from state to history.
2
The judgement interviewers reward is restraint. CQRS and event sourcing solve genuine problems — divergent read/write workloads, audit requirements, complex domains, building multiple specialised read views — but they introduce eventual consistency, more moving parts, and a steeper learning curve. They are not a default architecture; you apply them to the specific bounded contexts that benefit, while simpler CRUD suffices elsewhere. Being able to say when not to use them is as important as explaining how they work.