Event Sourcing vs CQRS
Event Sourcing and CQRS are two patterns that often appear together in microservices and domain-driven design — but they solve different problems. Event Sourcing stores state as a sequence of domain events instead of updating rows in place — giving you a complete audit trail and the ability to rebuild state at any point in time. CQRS (Command Query Responsibility Segregation) separates read and write models so each can be optimized independently.
Both patterns add significant complexity. Event Sourcing without a clear need creates an append-only log that is hard to query. CQRS without read/write contention creates two models to maintain for no benefit. This article explains when each pattern earns its complexity and how they work together in production systems.
Event Sourcing
In traditional CRUD, updating an order status overwrites the previous value — history is lost. Event Sourcing appends events to an immutable log: OrderCreated, ItemAdded, PaymentReceived, OrderShipped. Current state is computed by replaying events — never stored directly. This gives you a complete audit trail, time-travel debugging ("what was the state at 3pm yesterday?"), and the ability to create new projections from historical events.
Event stores (EventStoreDB, Apache Kafka as event log, Marten for .NET) append events with versioning for optimistic concurrency. Snapshots optimize replay — store the computed state every N events so you do not replay thousands of events on every read. Event Sourcing works best for domains with complex lifecycles: orders, bank accounts, insurance claims, and inventory.
Quick reference
- Best for: audit requirements, complex domain lifecycles, temporal queries, event-driven systems.
- Strengths: complete audit trail, time travel, new projections from old events, natural event-driven integration.
- Weaknesses: query complexity, eventual consistency, learning curve, snapshot management.
- Events are immutable — never update or delete, only append compensating events.
- Use snapshots every 100-1000 events to avoid replaying entire history.
- Event schema evolution: add new fields as optional, never remove or rename.
Remember this
Event Sourcing gives you perfect audit history — use it when the event log itself has business value.
CQRS
CQRS splits a single data model into two: a write model optimized for commands (create order, update inventory) and a read model optimized for queries (order dashboard, product catalog). The write model enforces business rules and emits events; the read model listens to events and builds denormalized views for fast queries.
This separation lets you scale reads and writes independently — 100 read replicas for the query side, one write node for commands. Different read models serve different screens: a summary view for the dashboard, a detailed view for the admin panel, a search index for full-text lookup. The trade-off is eventual consistency — after a command, the read model may lag by milliseconds to seconds.
Quick reference
- Best for: read-heavy apps, complex queries, different views of same data, independent scaling.
- Strengths: optimized read and write paths, independent scaling, multiple read models.
- Weaknesses: eventual consistency, two models to maintain, complexity for simple CRUD.
- Write side: validate commands, enforce invariants, emit domain events.
- Read side: listen to events, build denormalized views, serve queries.
- Do not use CQRS for simple CRUD — the overhead is not justified.
Remember this
CQRS separates reads from writes — use it when query patterns differ significantly from write patterns.
Using Event Sourcing and CQRS Together
Event Sourcing and CQRS complement each other naturally. The event store is the write model — commands append events. Read models are projections built by consuming those events. When an OrderPlaced event is appended, the order summary projection updates, the inventory projection decrements stock, and the notification projection sends an email.
This combination powers systems at scale: banking ledgers, e-commerce order management, and logistics tracking. The event log is the source of truth; read models are disposable — delete and rebuild from events if corrupted. Start with CQRS alone if reads and writes have different scaling needs. Add Event Sourcing when you need audit trails or temporal queries.
Quick reference
- Event store = write model. Projections = read models. Events connect them.
- Rebuild read models: replay all events from the beginning — disaster recovery built in.
- Frameworks: EventStoreDB, Axon Framework (Java), Marten ( .NET), Eventuate.
- Start simple: CRUD → CQRS (if read/write diverge) → Event Sourcing (if audit needed).
- Projections can lag — design UI for eventual consistency (optimistic updates, polling).
- Test projection rebuilds regularly — they are your disaster recovery mechanism.
Remember this
Combine them when you need both audit history and optimized reads — the event log feeds multiple read projections.
When NOT to Use These Patterns
Most applications do not need Event Sourcing or CQRS. A standard CRUD app with PostgreSQL handles 95% of business software. Adding event sourcing to a blog platform or task manager creates complexity with no benefit. Adding CQRS when you have one simple query per entity creates two codepaths to maintain.
Red flags that you might need these patterns: regulatory audit requirements, complex domain with many state transitions, read and write loads differ by 100x, or multiple consumers need different views of the same data. If none apply, stick with CRUD and a well-designed relational schema.
Quick reference
- Skip Event Sourcing if: no audit requirement, simple state, team lacks DDD experience.
- Skip CQRS if: reads and writes have similar patterns, small scale, simple queries.
- CRUD + PostgreSQL handles most business apps — do not over-engineer.
- Migration path: start CRUD, extract CQRS for hot read paths, add events when audit is required.
- Complexity budget: every pattern must earn its place with a concrete requirement.
- Interview tip: mention these patterns, explain trade-offs, but default to simpler solutions.
Remember this
Default to CRUD — adopt Event Sourcing and CQRS only when specific requirements justify the complexity.
Event Sourcing and CQRS are powerful patterns for complex domains with audit requirements and divergent read/write needs. They are not defaults — they are responses to specific problems. Understand them for system design interviews and architecture discussions, but reach for CRUD first. When the domain demands it, the event log becomes your most valuable asset: immutable, replayable, and the single source of truth.
Related Articles
Explore this topic