Skip to content
C Codeloom
Backend

CQRS vs Event Sourcing

CQRS and event sourcing are often mentioned together but solve different problems. This post separates them, shows how they combine, and when each is worth the complexity.

·4 min read · By Codeloom
Intermediate 10 min read

What you'll learn

  • What CQRS actually changes about your code
  • How event sourcing differs from a journal
  • When the two patterns combine well
  • When to leave them on the shelf

Prerequisites

  • Comfort with typical CRUD architectures

CQRS and event sourcing live in the same conference talks but answer different questions. CQRS is about how you shape your read and write paths. Event sourcing is about how you store state. Confusing them leads to either over-engineered systems or missing benefits people expected.

What and why

CQRS, command query responsibility segregation, separates the model used for writes from the model used for reads. A write goes through a command handler that enforces invariants. A read goes through a query handler that reads a denormalized view tailored to a specific screen or API. The two sides can use different databases, different schemas, and scale independently.

Event sourcing stores state as an append only log of domain events. Instead of overwriting a row when a customer changes their address, you append an AddressChanged event. The current state is derived by replaying events. This gives you a perfect audit trail, the ability to time travel, and a natural way to evolve projections.

You can use one without the other. Plenty of systems use CQRS with traditional CRUD storage on both sides. Many systems use event sourcing with a single read model. They compose well but are not a package deal.

Mental model

Picture a kitchen. CQRS is splitting the kitchen into a prep station (writes) and a serving line (reads). Each station is optimized for its job. Event sourcing is keeping every order ticket ever printed in a binder so you can reconstruct exactly what was cooked and in what order. The two ideas can coexist: a kitchen with separate stations that also keeps every ticket. But you can have either alone.

The mental shift for event sourcing is that the log is the database. The projections are caches you can rebuild any time. For CQRS, the shift is that “the model” is no longer a single class; it is at least two, one for changing the world and one for describing it.

Architecture

Combined, the two patterns produce a system where commands write events, events update one or more read models, and queries serve those read models.

Write side:
client -> command -> aggregate -> event store (append)

Projection side:
event store -> subscriber -> read model A (e.g. SQL view)
                          -> read model B (e.g. search index)
                          -> read model C (e.g. analytics warehouse)

Read side:
client -> query -> read model (pick the right one)
CQRS with event sourcing

The aggregate enforces business rules and decides which events to emit. The event store is the durable source of truth. Subscribers replay events into purpose built read models: a relational view for the UI, a search index for full text, a warehouse for reporting. New read models can be added later by replaying history.

Trade-offs

CQRS adds complexity in code organization. You maintain two models and an asynchronous link between them. The payoff is independent scaling, simpler queries, and the freedom to evolve sides separately. For high read to write ratios or screens that combine data from many aggregates, the win is large.

Event sourcing adds complexity in storage and evolution. Schemas change over time, but events are immutable, so you need versioning and upcasters. Debugging requires replaying history. The payoff is a complete audit trail, easy temporal queries, and the ability to derive new views from old data.

The combined approach maximizes both benefits and both costs. Eventual consistency between sides becomes a constant background concern. Read models can lag the write log by milliseconds or seconds, and your UX has to acknowledge that.

Practical tips

Start with CQRS only if you have asymmetric read and write needs. A simple CRUD app does not benefit. A reporting heavy SaaS, a feed service, or a workflow tool often does.

Start with event sourcing only where audit, time travel, or rich projections are actually required. Compliance heavy domains (finance, healthcare, accounting) almost always benefit. A typical CRUD admin panel almost never does.

Version events from day one. Even if you never plan to change them, you will. A small “version” field on every event saves enormous amounts of pain three years in.

Wrap-up

CQRS reshapes how reads and writes flow through your system. Event sourcing reshapes how you persist state. Used together, they enable powerful designs but ask a lot of the team. Used alone, each solves a specific real problem. Pick deliberately, not because the patterns sound impressive together.