skip to content

questions

6

CQRS separates the model used to handle commands (writes) from the model used to handle queries (reads). Is Event Sourcing a required part of implementing CQRS, or is it a separate, optional choice? Explain how the two typically fit together when a team does use both.

level: juniorimportance: must knowfreq 70%

answer

  1. orthogonal patterns
  2. ES = write persistence, CQRS = model split
  3. event log solves ES's query weakness via projections
  4. CQRS alone doesn't require an event log

basics

~20 s

CQRS just means writes and reads use different models. Event Sourcing means you store every change as an event instead of overwriting data. You can do CQRS without Event Sourcing, but when a team does use Event Sourcing, the event log naturally becomes the write side and the read side is built from those events.

solid answer

~50 s

CQRS and Event Sourcing are orthogonal patterns that happen to complement each other extremely well. CQRS just says: use a different model (and often different storage) for accepting commands than for serving queries; it says nothing about how the write model persists state — it could be a normal table updated in place. Event Sourcing says: persist state as an append-only sequence of events rather than mutable rows. When you combine them, ES supplies the write-side persistence (the event log is the 'database' for commands) and CQRS supplies the mechanism for turning that log into fast, query-optimized read models via projections. You can have CQRS without ES (state-stored write model, separate read replica), and ES without CQRS is technically possible but rare, since querying an event-sourced aggregate for anything beyond 'get by ID' is awkward without a projected model.

go deeper

for a junior

Should know the one-line distinction: CQRS splits models, ES changes how state is stored. Doesn't need to explain projections in depth.

for a middle

Should be able to explain why the two commonly appear together and name the event log as the write-side source of truth.

for a senior

Should articulate the trade-offs of pairing them (audit trail, retroactive read models vs. eventual consistency, operational overhead) and know when to reach for CQRS alone.

for a principal

Should be able to advise a team on whether to adopt the pairing at all for a given domain, weighing long-term schema evolution and organizational readiness for eventual consistency against the audit/replay benefits.

## Two patterns, one common confusion CQRS (Command Query Responsibility Segregation) and Event Sourcing (ES) are two separate architectural patterns that solve different problems, and it's easy to conflate them because they show up together so often in the same tutorials and production systems. - **CQRS** is about splitting the model that handles writes (commands) from the model that handles reads (queries). Instead of one class or one table serving both 'change the order' and 'show me the order list,' you build two models: a command model optimized for validating business rules and applying changes, and one or more query models optimized for however the UI or downstream consumer wants to read the data — denormalized, joined, pre-aggregated, whatever shape is fastest to serve. - **Event Sourcing**, by contrast, is a persistence strategy: instead of storing the current state of an entity as a row you overwrite in place, you store the full sequence of state-changing events that happened to it (`OrderPlaced`, `OrderShipped`, `OrderCancelled`) as an append-only log, and current state is derived by replaying those events. ## Either one stands alone Neither pattern requires the other. - You can build a perfectly good CQRS system where the command side just writes to a normalized relational table and publishes a domain event afterward for integration purposes — no event log, no replay, just a write model and a separately maintained read replica or materialized view. - Conversely, you could theoretically apply Event Sourcing to a system that still exposes one unified read/write model, though this is unusual in practice because querying an event-sourced aggregate for anything beyond 'get by ID' is awkward — you'd have to replay events to answer even simple list or filter queries, which is slow and doesn't scale. ## Why they are so often paired The reason the two are so often paired is that each one solves the other's weak spot. - **Event Sourcing's biggest practical problem is querying.** An append-only log of events is a fantastic write model (it captures full history, gives you an audit trail for free, and never loses information through in-place overwrites) but a terrible query model, because answering 'show me all overdue orders' means scanning and replaying potentially every event for every order. - **CQRS's biggest practical problem, when adopted alone**, is that it still needs some answer for how the write side persists state, and teams often reach for the same normalized schema they'd use in a CRUD app, which under-uses the pattern. Put together, Event Sourcing supplies the write-side persistence mechanism (the event log is the durable store for commands, and aggregates are reconstituted by replaying their own events), and CQRS supplies the mechanism for turning that log into however many purpose-built, denormalized read models the application needs, each kept up to date by a **projector** that subscribes to the event stream. The event log becomes the single source of truth; every read model is a derived, disposable view. ## The trade-off of pairing them The trade-off of pairing them is real, not free. On the plus side: - you get a full audit log with no extra engineering; - you can add new read models retroactively over historical data because the events are still there; - the write and read sides scale independently. On the cost side, the system becomes **eventually consistent by construction** — the read models lag the event log by however long the projector takes to catch up — and the team takes on real operational machinery: - an event store; - a projection/subscription mechanism; - schema evolution for events over years of production use; - a mental model shift for every engineer touching the write side, since 'update this field' is no longer a valid operation; you can only append a new event describing what happened. ## Three read models over one order stream A concrete example: an order-management system might have a single `Order` aggregate stream per order (events like `OrderPlaced`, `ItemAdded`, `PaymentAuthorized`, `OrderShipped`), while the read side maintains three independent projections built from that same stream: 1. a 'customer order history' table for the customer-facing UI; 2. a 'warehouse picking queue' table for fulfillment staff; 3. a 'revenue by day' rollup for finance dashboards. None of those three read models share a schema, none of them are ever updated in place from a UI action, and all three can be rebuilt from scratch by replaying the `Order` events if their projection logic changes — a capability a plain CRUD table with CQRS bolted on top doesn't give you for free.

  • If you have CQRS without Event Sourcing, how does the read model normally get its data?
    Typically the command model writes to its own normalized store, and either publishes an integration event after each successful write or the read model is refreshed by a change-data-capture (CDC) process reading the write database's transaction log. There's no per-aggregate event history here — just a signal that 'something changed, go re-fetch or re-derive.' The read model reflects the latest state, not the sequence of changes that produced it.
  • Why is it rare to see Event Sourcing used without CQRS in production?
    Without a separate query model, every read has to go through the same aggregate-reconstitution path as a write — replay events, build state, then filter or search in memory — which is fine for 'get by ID' but breaks down for anything list-like or reporting-like. In practice teams almost always add at least one projected read model as soon as they need a second kind of query, which is CQRS by definition, even if they didn't set out to build it.

Think of CQRS as deciding to have a separate cash register (writes) and a separate financial report (reads) instead of one ledger book serving both purposes. Event Sourcing is a decision about how the cash register itself keeps records — as a receipt tape of every transaction rather than a single running balance you erase and rewrite. You can have a receipt tape without splitting register from report, and you can split register from report while the register still just keeps a balance — but a receipt-tape register pairs beautifully with a separate report, because the report is built by summing the tape.

saying these in an interview costs you the question

  • Says Event Sourcing 'is' CQRS or that you can't have one without the other
  • Can't explain what problem each pattern solves independently
  • Assumes the read model is just 'a copy of the database,' not something derived by replaying/projecting events
  • Believes CQRS requires two separate databases as a hard rule

context

open as a page

In an event-sourced CQRS write model, before a command handler can validate and apply a new command against an aggregate (say, an existing Order), the aggregate's current in-memory state has to be produced somehow — there's no row to just SELECT. How does that reconstitution actually happen?

level: middleimportance: must knowfreq 75%

basics

~20 s

The system pulls every past event for that one specific order from the event log, in the order they happened, and feeds them one by one into a fresh, empty Order object, which updates itself a little with each event. By the end, that object looks just like the order does right now, and only then does the command get checked against it.

open as a page

In a CQRS system where the write side uses Event Sourcing, how does a read model — for example, a 'customer order summary' table used by the UI — get built and kept up to date from the event log? Walk through the mechanism end to end.

level: middleimportance: must knowfreq 85%

basics

~20 s

A separate small piece of code called a projector watches the event log for new events. Whenever it sees an event it cares about (like 'order shipped'), it updates a plain table shaped exactly for what the screen needs to show. The UI only ever reads from that table, never from the raw events.

open as a page

In a CQRS system where the write side uses Event Sourcing, a user submits a command that changes data, and the client immediately re-queries a read model to display the result — but the change is missing or shows stale data. Why does this happen structurally, and what are the common ways teams handle it?

level: seniorimportance: must knowfreq 70%

basics

~20 s

Saving the change (writing the event) and updating what the screen shows (the read model) are two separate steps done by two separate pieces of code, and the second one takes a little time to catch up after the first. If you check the screen data too fast, you can catch it before it's updated.

open as a page

You're designing the command/write side of a new CQRS system. Under what conditions is Event Sourcing genuinely worth adopting for that write side, and when would a simpler state-stored write model — a normal table updated in place, with domain events published afterward purely for integration — serve the domain just as well or better?

level: seniorimportance: should knowfreq 60%

basics

~20 s

Use Event Sourcing when you truly need a full history of every change, like an audit trail, or answering 'what did this look like last Tuesday.' If all you need is the current state and maybe a heads-up to other systems when something changes, a normal table that gets updated plus a 'this changed' notification is simpler and usually enough.

open as a page

A team running a CQRS system backed by Event Sourcing wants to add a brand-new read model over two years of historical order data, and separately needs to fix a bug in an existing projection's logic. What does deriving all read models from the event log make possible here that a 'read replica of the write database' approach would not, and what operational risks come with exercising that capability?

level: principalimportance: should knowfreq 50%

basics

~30 s

Because every past change was saved as an event, not thrown away, the team can build a new report over years-old data by replaying all those old events through brand-new logic, as if they were just now happening — something a normal database copy can't do, since it only ever has today's current numbers. The risk is that replaying millions of old events takes real time and computing power, and can strain the system if done carelessly.

open as a page