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?
answer
- history as first-class requirement -> ES
- retroactive read models over historical data
- CRUD-ish domain -> state-stored + integration event instead
- event schema evolution is a permanent tax
- mix per-aggregate, not all-or-nothing
basics
~20 sUse 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.
solid answer
~50 sEvent Sourcing earns its cost when the domain genuinely needs history as a first-class artifact: regulatory audit trails, financial ledgers, temporal queries ('what was this account's state on March 1st'), or domains where the sequence and cause of changes matters as much as the end state. It also pays off when you expect to need new read models over historical data that don't exist yet, since the event log lets you build those retroactively. It's the wrong tool when the domain is simple CRUD with no meaningful history requirement, when the team lacks operational maturity for eventual consistency and event schema evolution, or when low, predictable latency matters more than audit completeness. In those cases, a state-stored write model that publishes an integration event on each state change gets most of CQRS's read/write separation benefit without the replay, snapshotting, and schema-versioning burden of full Event Sourcing.
go deeper
Should know that ES is optional and be able to give one example reason to use it (audit trail) and one reason not to (simplicity).
Should list a few concrete drivers on each side and understand the state-stored-plus-integration-event alternative exists.
Should weigh the trade-offs explicitly, know the decision can be made per-aggregate, and mention schema evolution as an ongoing cost of choosing ES.
Should be able to make and defend this call across a whole system's bounded contexts, anticipating future retroactive-read-model needs and organizational readiness for eventual consistency, not just the current domain requirement.
## The persistence choice is a separate decision CQRS only mandates that reads and writes go through different models; it says nothing about how the write model persists its own state, and that persistence choice is genuinely a separate design decision with its own cost-benefit analysis. Event Sourcing is one valid way to implement the write side of a CQRS system, but it is not the default, and treating it as 'what CQRS requires' leads teams to adopt real operational cost for no corresponding domain benefit. ## Three cases where Event Sourcing earns its keep 1. The strongest, least controversial case for Event Sourcing is a domain where **history is a first-class business requirement**, not an afterthought. A financial ledger needs every debit and credit preserved forever, in order, immutable, because that sequence is the audit trail regulators and auditors require — you can't satisfy 'prove this account's balance on any past date' with a table that only stores current balance. Similarly, domains with legal or compliance retention requirements (healthcare records, insurance claims, trading systems) often need to reconstruct 'what did we believe was true at time T' months or years later, which is exactly what event replay gives you and a state-stored table structurally cannot, once a row has been overwritten. 2. A second strong case is when the **business logic itself is fundamentally about a sequence of state transitions with meaningful causality** — a workflow or saga where 'this happened, which caused that, which caused this rejection' is the actual thing being modeled, and collapsing it down to 'current status: rejected' would throw away information the domain experts actually reason about day to day. 3. A third, more forward-looking case: if you're reasonably confident the product will need **new ways of slicing historical data that don't exist yet** — new dashboards, new analytics, new compliance reports — an event log lets you build those retroactively over years of past data the day you think of them, because the raw facts were never thrown away. A state-stored system can only ever answer questions about the shape of data it was explicitly designed to keep; if a given historical query wasn't built for on day one, that history is simply gone. ## What it costs Against all of this sits a real and often underestimated cost. - Every command handler now goes through the load-fold-decide-append reconstitution cycle instead of a simple SELECT/UPDATE. - Long-lived aggregates need a snapshotting strategy or they get slower over years. - Every event that ever gets appended is effectively a permanent, versioned public contract, because old events must still be readable and interpretable years later even after the business logic that produced them has changed — **event schema evolution** is a genuinely hard, ongoing engineering discipline that never goes away for the life of the system. - The read side is unavoidably eventually consistent, which pushes UX and API-design complexity onto every team building on top of the write model. - Debugging shifts in character: instead of 'what does this row say right now,' engineers have to reason about 'what sequence of events produced this state,' which is a real cognitive tax for a team without prior ES experience. ## The pragmatic middle ground For domains that are simple, high-volume CRUD with no meaningful audit or temporal-query requirement — a user-profile service, a product catalog, a shopping cart — none of Event Sourcing's benefits are being cashed in, and the team is paying its full operational and cognitive cost for nothing. In those cases, the pragmatic middle ground is **'CQRS without ES'**: the write side is a normal table updated in place inside a transaction, and immediately after a successful write, the same handler publishes a domain event purely for integration — other services and read-model projections subscribe to that event stream the same way they would in a full ES system, but the write side itself never has to replay anything to answer a query or reconstitute an aggregate; it just SELECTs its own row. This gets most of CQRS's core benefit — decoupled, independently-scalable, purpose-built read models — without committing to full event-log-as-source-of-truth semantics on the write side. ## One e-commerce platform, both approaches A concrete real-world split: a company running an e-commerce platform might use full Event Sourcing for its `Order` and `Payment` aggregates, where audit trail and dispute investigation genuinely matter and regulators may ask 'show me exactly what happened to this payment,' while using a plain state-stored write model with published integration events for its Product Catalog and User Profile services, where 'current state plus a change notification' is all any consumer has ever actually needed.
- Can a single system use Event Sourcing for some aggregates and a state-stored write model for others?Yes, and this is common in practice — the decision is made per-aggregate or per-bounded-context based on that specific domain's need for history, not as a single system-wide architectural mandate. An Order aggregate with audit requirements can be event-sourced while a ProductCatalog aggregate in the same system stays state-stored.
- If a team picks the state-stored-plus-integration-event approach, do they lose the ability to build new read models later?They lose the ability to build read models over data changes that happened before the integration events started being captured and durably retained, since old state transitions weren't preserved as discrete facts. Going forward, as long as the integration events themselves are retained somewhere with long retention, new projections can still be built from that point onward — just not retroactively over pre-existing history.
- What's a warning sign that a team adopted Event Sourcing for the wrong reason?If nobody can name a concrete audit, compliance, temporal-query, or causality requirement the domain actually has — and the honest answer to 'why did we do this' is 'it's the modern/correct way to do CQRS' — that's a sign the team paid ES's real operational cost without a domain need pulling it.
It's like deciding whether to keep a full itemized bank statement (every transaction, forever) versus just a running balance with a text alert when it changes. A landlord tracking rent balances for a duplex probably just needs the running balance and a notification; a bank handling disputes and audits needs the full itemized history, no matter the storage cost.
saying these in an interview costs you the question
- Claims Event Sourcing is required to do CQRS 'properly'
- Can't name a concrete domain requirement (audit, compliance, temporal query, causality) that justifies ES
- Ignores event schema evolution as an ongoing cost
- Treats the ES-vs-state-stored choice as all-or-nothing across an entire system rather than per aggregate/bounded context