Back to Library
system_design

Event Sourcing

Event sourcing stores every state change as an immutable event log rather than storing current state directly.

architecturedatabasespatterns

What is event sourcing?

In traditional systems, you store the current state of an entity: {order_id: 123, status: "shipped", total: $49.99}. In event sourcing, you store the sequence of events that led to that state: [OrderCreated, ItemAdded, PaymentProcessed, OrderShipped]. Current state is derived by replaying events.

Core Concepts

Event

An immutable fact that something happened: OrderShipped { order_id: 123, timestamp: ..., carrier: "FedEx" }. Events are named in past tense - they represent things that have already occurred.

Event Log (Event Store)

A persistent, append-only log of all events, ordered by time. This log is the single source of truth. You never update or delete events.

Current State

Derived by replaying all events for a given entity from the beginning. This is the projection or aggregate state.

OrderCreated  -> status: pending
PaymentProcessed -> status: paid
OrderShipped  -> status: shipped

Advantages

Complete Audit Trail

The event log contains every state transition with full context. Perfect for compliance, debugging, and forensic analysis. "What was the state of order 123 at 2:00pm yesterday?" - replay events up to that timestamp.

Temporal Queries

Query state at any point in time by replaying up to that point. Impossible with traditional state storage without snapshot tables.

Event-Driven Integration

Other services can subscribe to the event stream and react asynchronously. Adding a new consumer (analytics, notifications) doesn't require changing the producer.

Debugging

Reproduce bugs by replaying the exact sequence of events that caused them.

Disadvantages

Query Complexity

Querying current state requires replaying events or maintaining pre-computed projections (read models). Simple queries like "get all active orders" require a separate read model updated by events.

Snapshots Required at Scale

For entities with thousands of events, replaying from scratch on every read is expensive. Solution: persist snapshots of state at regular intervals, then replay only events since the last snapshot.

Schema Evolution

Events are immutable - you can't change past events. When your event schema needs to change, you must version events and handle multiple versions in your replay logic.

Eventual Consistency

Read models (projections) are updated asynchronously from the event stream. There's a lag between write and readable state.

When to Use Event Sourcing

✅ Domain has complex business rules with many state transitions (e-commerce orders, financial transactions, reservations) ✅ Auditability is a hard requirement (finance, healthcare, legal) ✅ Need to support temporal queries ✅ Event-driven integration with multiple downstream consumers

❌ Simple CRUD with no meaningful history ❌ Team unfamiliar with the pattern - high accidental complexity ❌ Low write volume where complexity outweighs benefits

Event Sourcing + CQRS

Event sourcing is almost always paired with CQRS (Command Query Responsibility Segregation): writes go through the event log, reads come from pre-computed projections. This separates the write model (events) from the read model (optimised for queries).

Interview Angle

Event sourcing is a senior-level pattern. Bring it up for: "How would you implement an order management system?" or "How do you ensure an audit trail?" Then immediately address its costs: projection complexity, snapshots, schema evolution. Showing you know the tradeoffs is more impressive than just naming the pattern.

Recommended Resources