Skip to content
Event Sourcing Explained: Store What Happened, Not Just Current State 6 min

Event Sourcing Explained: Store What Happened, Not Just Current State

SD
ScaleDojo
May 11, 2026
6 min read1,384 words
Event Sourcing Basics: Storing What Happened Instead of Current State

The Event Sourcing pattern is one of those ideas that sounds academic until you see what breaks without it. Here's a real example of what that looks like at scale.

How LEGO Rebuilt Its Entire E-Commerce Platform with Event Sourcing

In 2019, LEGO's online store was struggling with a traditional CRUD database. During product launches (like Star Wars sets), thousands of customers would add items to carts simultaneously. The system could not answer basic questions: 'Why was this customer's cart emptied?' or 'What was the inventory count 5 minutes ago?' After a particularly disastrous product launch where overselling cost them millions, LEGO rebuilt their cart and inventory system using event sourcing. Every cart addition, removal, price change, and inventory adjustment was stored as an immutable event. They could now replay any customer's shopping session, reconstruct inventory at any timestamp, and most importantly - detect and prevent overselling by replaying the exact sequence of events that caused it.

Traditional CRUD vs Event Sourcing

Traditional CRUD (storing current state):

  UPDATE accounts SET balance = 500 WHERE id = 42;

  Account 42: balance = $500
  Q: How did it get to $500?  A: No idea. History is gone.
  Q: What was the balance yesterday?  A: No idea.
  Q: Did someone deposit then withdraw?  A: No idea.

Event Sourcing (storing what happened):

  Event Store for Account 42:
  +-----+-------------------+--------+---------------------+
  | Seq | Event Type        | Amount | Timestamp           |
  +-----+-------------------+--------+---------------------+
  |  1  | AccountOpened     | $0     | 2024-01-01 09:00:00 |
  |  2  | MoneyDeposited    | $200   | 2024-01-01 10:00:00 |
  |  3  | MoneyDeposited    | $500   | 2024-01-02 14:00:00 |
  |  4  | MoneyWithdrawn    | $150   | 2024-01-03 09:30:00 |
  |  5  | MoneyWithdrawn    | $50    | 2024-01-04 16:00:00 |
  +-----+-------------------+--------+---------------------+

  Current balance: $0 + $200 + $500 - $150 - $50 = $500
  Balance on Jan 2: $0 + $200 = $200
  Full audit trail: every dollar is accounted for.

Event Sourcing Architecture

Knowing that events get stored is only half the picture. The more useful question is how a request actually moves through a system like this-where it enters, what it touches, and how it comes back out as something a user can read on a screen. That's what the diagram below lays out: one path for writes, a separate path for reads, and the event store sitting in the middle as the one thing both sides agree is true.Event Sourcing Components:

Command Side (Write) Query Side (Read)
+------------------+ +------------------+
| Command Handler | | Event Handler |
| (business logic) | | (projection) |
+--------+---------+ +--------+---------+
| ^
v |
+------------------+ +--------+---------+
| Event Store |---events---->| Read Model DB |
| (append-only) | (async) | (materialized |
| (source of truth)| | view) |
+------------------+ +------------------+

Write path:
1. Command arrives: TransferMoney($100, from=A, to=B)
2. Load events for Account A, replay to get current state
3. Validate: does A have $100? (business rule)
4. Generate events: MoneyWithdrawn(A, $100), MoneyDeposited(B, $100)
5. Append events to event store (atomic write)

Read path:
1. Event handlers listen for new events
2. Update read-optimized projections (denormalized views)
3. Queries read from projections (fast, no event replay needed)

Key insight: the event store is the source of truth.
Read models are disposable - delete and rebuild from events.

Snapshots: Solving the Replay Problem

The architecture above works fine on paper, but it quietly assumes something: that replaying events is cheap. It isn't, forever. An account that's been active for a few years can rack up tens of thousands of events, and reconstructing its state by replaying every single one, every single time someone hits "check balance," starts to hurt. This is the part of event sourcing nobody mentions in the pitch meeting -and the part that actually decides whether the pattern is usable at scale.

The Replay Performance Problem:

  Account opened in 2020. By 2024: 50,000 events.
  To get current balance: replay all 50,000 events.
  At 1ms per event: 50 seconds to load one account!

  Solution: Periodic Snapshots

  Events: [1] [2] [3] ... [999] [SNAPSHOT @ 1000: balance=$4,230]
          [1001] [1002] ... [1050]

  To get current state:
  1. Load latest snapshot (balance=$4,230 at event 1000)
  2. Replay only events 1001-1050 (50 events, not 50,000)
  3. Current balance calculated in ~50ms

  Snapshot frequency: every 100-1000 events (depends on event size)
  Storage: snapshots are just serialized state, small compared to event log

When Event Sourcing Makes Sense

None of this is worth adopting just because it sounds impressive in a design doc. Event sourcing solves real problems, but it also adds a real amount of machinery-snapshots, projections, eventual consistency -and dragging all that into a system that never needed it is a common mistake. The honest question to ask isn't "is this a cool pattern," it's "will I actually replay this history, or debug with it, or get audited against it." If the answer is yes, it earns its complexity. If not, plain CRUD will serve you better and get out of your way faster.Decision Matrix:

Use Event Sourcing When: Use CRUD When:
--------------------------- -------------------------
Audit trail required (finance, law) Simple CRUD operations
Need to debug 'what happened' No regulatory requirements
Multiple read models from same data Single view of data
Domain has complex state machines Simple status changes
Need time-travel queries Current state is sufficient
Regulatory compliance (SOX, HIPAA) Prototype / MVP

Real-World Event Sourcing:
- Banking: every transaction is an event (regulatory requirement)
- Git: every commit is an event (replay = checkout)
- Accounting: double-entry ledger IS event sourcing
- Figma: every stroke is an operation (enables undo/redo)
- Kafka: log-based storage IS event sourcing

Event Sourcing Pitfalls

  • Schema evolution: events are immutable. When event format changes, use upcasting (transform old events to new format on read).

  • Eventual consistency: read models update asynchronously. UI might show stale data for milliseconds.

  • Storage growth: events accumulate forever. Plan for archival/compaction strategy from day one.

  • Complexity overhead: significantly more moving parts than CRUD. A to-do app does not need event sourcing.

  • Querying: you cannot query events directly like SQL tables. You need materialized projections for each query pattern.

CQRS and Event Sourcing: Why They're Almost Always Paired

Look back at the architecture diagram -there's already a command side and a query side sitting there, split apart. That split has a name: CQRS (Command Query Responsibility Segregation), and it's the pattern that makes event sourcing actually usable for real applications.

Here's why they end up together so often. Event sourcing is excellent at capturing writes -every change becomes an event, appended to the log, done. But raw events are a poor shape to read from. Nobody wants to replay fifty thousand events just to render a dashboard. CQRS solves that half of the problem: commands go one way and produce events, queries go a completely different way and hit projections built specifically to answer them fast.

They're independent patterns, technically -you can use CQRS on a normal CRUD database with no event log in sight, and you can use event sourcing with a single, simple read model instead of full CQRS. But in practice, the moment your event-sourced system needs more than one way to look at its data, you're already doing CQRS whether you named it that or not.

Event Sourcing in System Design Interviews

This combination -event sourcing for writes, CQRS for reads -is one of the most reliable ways to earn points in a system design interview once the domain calls for it. It signals that you're not just storing data, you're thinking about how state actually gets produced and consumed differently, which is exactly what separates a junior answer from a senior one.

Interview Tip

Event sourcing appears in interviews for financial systems, e-commerce, and collaborative editing. The key phrase: 'store facts about what happened, not current state.' Draw the command side (event store) and query side (projections) separately - this naturally leads into CQRS. When asked about the performance problem, explain snapshots. When asked about downsides, mention eventual consistency between event store and projections, and schema evolution challenges. The advanced insight: event sourcing and CQRS are complementary but independent patterns - you can use CQRS without event sourcing and vice versa.

Key Takeaway

Event sourcing stores what happened (immutable events) instead of current state. This gives you complete audit trails, time travel, and the ability to rebuild state from scratch. Use snapshots to solve replay performance. But it adds significant complexity - use it only when you genuinely need the history (financial systems, audit requirements, collaborative applications). Never use it for simple CRUD.

Reading about Event Sourcing is one thing -actually building one is where it clicks. Start Building Free on ScaleDojo → and design an event-sourced system yourself, with instant AI feedback on every decision.

Enjoyed this article?

Share it with your network to help others level up their system design skills.

Discussion0

Join the Discussion

Sign in to leave comments, reply to others, or like insights.

Sign In to ScaleDojo

No comments yet. Be the first to start the thread!

Related Articles

Enjoyed this content?

Your support keeps us creating free resources

We put a lot of hours into researching and writing these guides. If it helped you, consider buying us a coffee. Every bit goes toward keeping ScaleDojo's content free and growing.

$

One-time payment via Stripe. ScaleDojo account required.

ScaleDojo Logo
Initializing ScaleDojo