Skip to main content

📜 Event Sourcing

Store events, not current state

The Bank Ledger Analogy

Traditional savings:

  • Piggy bank: Only shows current amount
  • Where did my money go? No idea!

Bank ledger:

  • Every transaction recorded: Deposit 100,Withdraw100, Withdraw 20, Transfer $50
  • Full history: Exactly how you got here
  • Can recalculate balance from the ledger anytime

Event sourcing is a bank ledger for your app. Store every change as an event.


What Is Event Sourcing?

Traditional: Store current state
  User { balance: 80 }

Event Sourcing: Store all events
  1. AccountCreated { balance: 0 }
  2. MoneyDeposited { amount: 100 }
  3. MoneyWithdrawn { amount: 20 }

Current state? Replay events: 0 + 100 - 20 = 80

Key Difference

Traditional (State):
  Overwrite with each change
  Only know "what is"
  History lost

Event Sourcing:
  Append each change
  Know "what happened"
  Full history preserved

How It Works

Writing

User action: "Withdraw $20"

1. Validate business rules
2. Create event: MoneyWithdrawn { amount: 20 }
3. Append to event store (treat existing events as immutable)
4. Update read model (current state cache)

Reading Current State

Option A: Replay all events
  Load events → Apply each → Current state

Option B: Use snapshot + recent events
  Load snapshot (state at event 100)
  Apply events 101-105
  Current state

Option C: Query read model
  Pre-computed current state
  Updated when events are stored

Event Store

Append-only log of events:

┌─────┬────────────────────┬───────────────────────────┐
│ ID  │ Type               │ Data                      │
├─────┼────────────────────┼───────────────────────────┤
│ 1   │ AccountCreated     │ { id: 123 }               │
│ 2   │ MoneyDeposited     │ { amount: 100 }           │
│ 3   │ MoneyDeposited     │ { amount: 50 }            │
│ 4   │ MoneyWithdrawn     │ { amount: 20 }            │
│ 5   │ AccountFrozen      │ { reason: "suspicious" }  │
└─────┴────────────────────┴───────────────────────────┘

Events are immutable.
Typically treated as append-only.
Avoid changing or deleting historical events.

Why Use Event Sourcing?

1. Complete Audit Trail

Traditional: "Balance is -$500. What happened?"
Event Sourcing: Shows every transaction that led there.

Perfect for:
  - Financial systems
  - Medical records
  - Legal compliance

2. Time Travel

Q: "What was the account state on March 1st?"
A: Replay events up to March 1st.

Debugging: Reproduce exact state at time of bug.

3. Replay and Rebuild

Bug in calculation logic?
  1. Fix the logic
  2. Replay all events
  3. Correct state!

Can't do this with lost state.

4. Event-Driven Architecture

Events can trigger:
  - Analytics updates
  - Notifications
  - Third-party integrations
  - Multiple read models

Decoupled systems react to events.

Snapshots

The Problem

Account with 10,000 events.
Replay all 10,000 to get current state?
Too slow!

The Solution

Periodically save snapshots:

Snapshot at event 1000:
  { balance: 5000, frozen: false }

Get current state:
  1. Load snapshot (event 1000)
  2. Replay events 1001-10000

Much faster!

Snapshot Strategy

Options:
  - Every N events
  - Every N minutes
  - On specific events
  - On demand

Projections (Read Models)

Events optimized for writing.
Queries need different structures.

Solution: Projections (read models)

Events → Process → Read Model

Account Events → Balance Projection
Order Events → Order Summary Projection
Activity Events → Dashboard Projection

Multiple Projections

Same events, different views:

Order Events →
  → Customer Order History (by customer)
  → Product Sales Report (by product)
  → Daily Revenue (by date)

Each optimized for its use case.

Event Sourcing + CQRS

Common pairing:

CQRS: Separate read and write models
Event Sourcing: Write model is events

Write side:
  Commands → Events → Event Store

Read side:
  Events → Projections → Read Database
  Queries → Read Database → Response

Scales reads and writes independently.

Challenges

1. Complexity

More moving parts:
  Event store + Read models + Projections

Simple CRUD might not need this.

2. Event Schema Evolution

Old events: { amount: 100 }
New events: { amount: 100, currency: "USD" }

Need versioning and migration strategies.

3. Eventually Consistent

Event written → Projection updated
Small delay between.

Read model might be slightly behind.

4. Querying Events

"Find all accounts with balance > $1000"
Can't query events directly!

Need projections or materialized views.

When to Use

Good Fit

✓ Audit requirements
✓ Complex business logic
✓ Need to understand how state evolved
✓ Time-travel debugging valuable
✓ Multi-view requirements (many read models)

Probably Not Needed

✗ Simple CRUD applications
✗ No audit requirements
✗ Single view of data
✗ Small, simple domains

Common Mistakes

1. Storing Commands, Not Events

Bad: "UpdateBalanceCommand"
Good: "MoneyWithdrawn" (what actually happened)

Events are facts, not intentions.

2. Too Much Detail in Events

Event: { user, time, balance, ip, browser, screen, ... }

Store what's needed. Derive what you can.

3. Mutable Events

Avoid updating events.
They represent historical facts.

Need correction? Add new compensating event.

FAQ

Q: Isn't this just logging?

Logs are side effects. Events are the source of truth. You rebuild state from events.

Q: How do I delete data (GDPR)?

Crypto shredding: Encrypt personal data, delete key. Or: Tombstone events marking data as removed.

Q: What database for event store?

Purpose-built: EventStoreDB, Axon Or: PostgreSQL, MongoDB with append-only pattern

Q: How big do event stores get?

Large! But events compress well. Archiving older events is common.


Summary

Event sourcing stores all changes as events, enabling complete history, time travel, and flexible rebuilding.

Key Takeaways:

  • Store events, not just current state
  • Usually append-only (avoid updating/deleting historical events)
  • Replay events to get state
  • Use snapshots for performance
  • Projections create read models
  • Perfect for audit, compliance, complex domains
  • More complex than traditional CRUD

Event sourcing tells you not just where you are, but how you got there!

Leave a Comment

Comments (0)

Be the first to comment on this concept.

Comments are approved automatically.