omiid
homenotebookai usage

How CQRS is different than Event Sourcing

August 18, 2024 · Updated on August 09, 2026

CQRS and Event Sourcing get treated as one pattern with two names. They are two separate patterns. The difference is what each one changes: CQRS changes how your application is structured, Event Sourcing changes how your data is stored. You can adopt either one alone, and you can combine them.

I write short, practical notes like this one. Get the next one by email:

Unsubscribe anytime.

CQRS splits reads from writes

CQRS stands for Command Query Responsibility Segregation. The CQRS pattern puts write operations behind one path and read operations behind another. Commands change state. Queries return state. Neither path calls into the other.

In CQRS, we split our application's operations into two models:

  1. Command model: Handles write operations (create, update, delete)
  2. Query model: Handles read operations

This separation allows us to optimize each model independently. For example, we might use a normalized database for our command model to ensure data integrity, while our query model could use a denormalized database for faster reads.

Event Sourcing stores changes instead of current state

A normal database stores the current value of a row and overwrites it on every update. The Event Sourcing pattern stores the changes themselves in an append-only event store and derives the current value from them.

In Event Sourcing:

  1. We store every state change as an event
  2. The current state is derived by replaying all events
  3. The event log becomes the single source of truth

Because nothing is overwritten, you can reconstruct the state of your application at any point in time by replaying events up to that point.

CQRS vs Event Sourcing: what each one costs you

The two patterns solve different problems, so compare them on what they add and what they charge for.

Pros of CQRS

  1. Scalability: You can scale read and write operations independently
  2. Performance: Optimized read and write models can lead to better performance
  3. Flexibility: Easier to adapt to changing business requirements

Cons of CQRS

  1. Complexity: Two models mean more code to maintain
  2. Eventual consistency: The read model might lag behind the write model
  3. Learning curve: It's a significant shift from traditional CRUD operations

Pros of Event Sourcing

  1. Audit trail: Complete history of all changes
  2. Temporal queries: Ability to determine the state at any point in time
  3. Event replay: Easier to fix bugs by replaying events

Cons of Event Sourcing

  1. Complexity: Requires a different way of thinking about data
  2. Performance concerns: Replaying a large number of events can be slow
  3. Event schema evolution: Changing event structures can be challenging

CQRS and Event Sourcing are not mutually exclusive

They often work well together. You could use Event Sourcing in your command model to capture all changes as events, and then use CQRS to separate your read and write concerns. In practice, the command side publishes those events to a message broker, which delivers them to the query side. RabbitMQ's exchange and queue model is a common choice for that routing layer.

But just because you can use them together doesn't mean you always should. Each pattern comes with its own complexity, and combining them multiplies that complexity. Consider your specific use case and requirements before adopting either one.

If you only need faster reads, start with CQRS. If you need a full audit trail, start with Event Sourcing. Reach for both only when you need both.

tl;dr

CQRS separates read and write operations into distinct models, optimizing each for its specific purpose.

Event Sourcing stores all state changes as events, allowing for complete historical reconstruction.

While they're different patterns, they can be used independently or together, each bringing its own set of advantages and challenges to the table.

Join My Newsletter

Occasional notes on software, tools, and things I learn. No spam.

Unsubscribe anytime.

Continue Reading
  • Tuning Postgres and pgvector: the three knobs that matter08-18-2026 · Most pgvector performance problems come down to three settings. This post shows how to read an ANN query plan and tune ef_search, shared_buffers, and work_mem in the right order.
  • AI text watermarking: how it works and what it can't do08-16-2026 · Claude now watermarks its text. The watermark changes where the randomness in word choice comes from, not what the model can say. Here is the whole pipeline, with simulations you can poke at.
  • HNSW vs IVFFlat: choosing and building your pgvector index08-14-2026 · Past a few hundred thousand rows, an exact scan stops being fast enough. Here is how to pick between HNSW and IVFFlat and build the index without locking the table.
  • Vector search relevance: chunking, metadata, and the 0.81 problem08-11-2026 · Most bad vector search results come from one of three failure modes: chunking, modality mismatch, or a confused model. Each one has a specific diagnostic and a specific fix.
  • pgvector setup: your first multimodal query in TypeScript08-03-2026 · One Postgres table can hold text and screenshot embeddings in the same vector column. This post sets up the schema, the Voyage embedding call, and the first query that returns both.