Menu

Event Sourcing

Store every state change as an immutable event: event stores, projections, snapshots, replay, and the relationship between event sourcing and CQRS.

20 min readHigh interview weight

The Core Idea

Traditional systems store only the current state of an entity — update a row in the database and the previous state is gone. Event Sourcing inverts this: instead of storing current state, you store an ordered log of every event that ever happened. Current state is derived by replaying events from the beginning.

Think of your bank account. The balance is not stored directly — it is calculated by replaying all deposits, withdrawals, and transfers. Git is another example: the current state of your codebase is derived from the history of commits. Event sourcing brings this same auditability and time-travel capability to your application data.

Loading diagram...
Event store as append-only log — current state is derived by replaying events.

Key Components

ComponentRoleExample
EventImmutable fact describing something that happened`OrderPlaced`, `PaymentFailed`
Event StoreAppend-only log of events per aggregateEventStoreDB, Kafka, DynamoDB streams
AggregateDomain entity that produces and handles events`Order`, `Account`, `Inventory`
ProjectionDerived read model built by replaying eventsSQL view, Redis hash, Elasticsearch doc
SnapshotCheckpoint of aggregate state to speed up replayStored every N events
Command HandlerValidates input, loads aggregate, applies eventsDomain service layer

The Event Sourcing Flow

Loading diagram...
Full event sourcing flow: load aggregate by replaying, append new event, update projections.

Snapshots

If an aggregate has thousands of events, replaying from the beginning on every command becomes slow. Snapshots solve this: periodically serialize the aggregate state and store it alongside a version number. On the next load, fetch the latest snapshot and only replay events after that snapshot's version.

typescript
// Pseudo-code: loading an aggregate with snapshot optimization
async function loadOrder(orderId: string): Promise<Order> {
  // 1. Try to load the latest snapshot
  const snapshot = await eventStore.getSnapshot(orderId);

  let order: Order;
  let fromVersion: number;

  if (snapshot) {
    order = Order.fromSnapshot(snapshot.state);
    fromVersion = snapshot.version + 1;
  } else {
    order = new Order();
    fromVersion = 0;
  }

  // 2. Replay only events AFTER the snapshot
  const events = await eventStore.getEvents(orderId, fromVersion);
  for (const event of events) {
    order.apply(event);
  }

  return order;
}

Event Sourcing + CQRS

Event sourcing pairs naturally with CQRS. The write side uses the event store as its source of truth. Every appended event flows into projectors that maintain denormalized read models in whatever shape queries need. Different projectors can build completely different views of the same events — an order might power an `order_summary` table in Postgres, an Elasticsearch document for search, and a Redis sorted set for a delivery dashboard.

ℹ️

Event Versioning Is Critical

Events are immutable and may be replayed years later. When your domain evolves, you cannot change old events. Instead, version them: `OrderPlaced_v1`, `OrderPlaced_v2`. Upcasters transform old event versions to new formats during replay. Plan your event schema evolution strategy early — it is much harder to retrofit.

Benefits and Costs

BenefitCost
Complete audit log — who changed what and whenEvent store can grow very large without compaction
Time-travel debugging — replay to any point in timeEventually consistent read models
Temporal queries — 'what was the state on date X?'Steep learning curve for developers
Decoupled projections — add new read models without touching write logicEvent versioning and upcasting complexity
Natural integration events for downstream consumersReplaying millions of events to recover state is slow without snapshots

Real-World Examples

LinkedIn uses event sourcing for its activity feed — every action (like, share, comment) is an event appended to a stream. Walmart uses it for inventory management, enabling them to replay state for audit and dispute resolution. Axon Framework (Java) and EventStoreDB are popular production implementations. Apache Kafka is frequently used as an event store, though it lacks built-in aggregate-scoped streams and optimistic concurrency.

💡

Interview Tip

When an interviewer asks about event sourcing, lead with the business benefits — audit trail, time travel, decoupled projections — before diving into implementation. Then discuss the trade-offs: eventual consistency, event versioning, and snapshot strategies. Mention that you would pair it with CQRS and use something like Kafka or EventStoreDB as the backing store. A common follow-up is 'how do you handle schema changes?' — answer with versioned events and upcasters.

📝

Knowledge Check

5 questions

Test your understanding of this lesson. Score 70% or higher to complete.

Ask about this lesson

Ask anything about Event Sourcing