Event Sourcing

Messaging & Async

Store state changes as an append-only sequence of events and build projections

Core Idea

Persist domain events as the source of truth. Reconstruct current state by replaying events and maintain materialized views for queries.

When to Use

When auditability and temporal queries are required, or complex domains benefit from CQRS and projections.

Recognition Cues
Indicators that this pattern might be the right solution
  • Strict audit/logging requirements
  • Need to time-travel or rebuild state
  • Multiple read models per domain

Pattern Variants & Approaches

Overview
Append immutable domain events to an event store; project into read models for queries and rebuild by replay.

Overview Architecture

AppendStreamUpdateQuery⚙️Application💾Event Store⚙️Projector💾Read Model

When to Use This Variant

  • Strict audit trail
  • Temporal queries
  • Multiple read models

Use Case

Financial ledgers, audit-heavy systems, and complex domains with evolving views.

Advantages

  • Complete history
  • Optimized projections
  • Independent read models

Implementation Example

# Event store interactions
eventStore.append(event)
projector.on(event, updateReadModel)
readModel.query(params)
Tradeoffs

Pros

  • Full audit trail and temporal insights
  • Multiple optimized read models (CQRS)
  • Easier to evolve projections independently

Cons

  • High conceptual and operational complexity
  • Event evolution and migration costs
  • Eventual consistency and replay times
Common Pitfalls
  • Event schema evolution and upcasting complexity
  • Long replays without snapshots/compaction
  • Out-of-order or duplicate event handling
  • Assuming exactly-once delivery
Design Considerations
  • Immutable, versioned event contracts
  • Snapshots and log compaction for fast recovery
  • Idempotent projections and replay tooling
  • Partitioning by aggregate for ordering
  • Checksum/validation and dead letter handling
Real-World Examples
EventStoreDB

Purpose-built event store

Clusters with billions of events
Banks

Ledgering via event streams

Regulated, audit-heavy systems
Microservices

Kafka-backed event-sourced services

Large distributed estates
Complexity Analysis
Scalability

Partitioned logs with compaction

Implementation Complexity

High - Contracts, snapshots, replay

Cost

Medium - Storage and tooling