top of page

Event Sourcing

  • Writer: Pradeep P
    Pradeep P
  • 3 days ago
  • 3 min read

Layer 4 · Post 10 of 11

← Previous: CQRS → Next: Change Data Capture

Layer 4 — Data · Post 49 of 88

Event sourcing stores every change as an event, then rebuilds state by replaying them. The log becomes the source of truth.

What you'll learn

  • Why the event log is the system of record, and snapshots are just a cache of the fold

  • How this pairs with CQRS without being the same thing

  • Versioning, GDPR, and "we can always rebuild" as operational traps

The idea in one minute

Most databases store current state: orders.status = 'shipped'. Event sourcing stores what happened: OrderPlaced, PaymentCaptured, OrderShipped. Current state is a function of the log — replay events in order.

e1 OrderPlaced e2 PaymentCaptured e3 OrderShipped | v fold --> { status: shipped, paid: true } // derived

The write model is an append-only stream per aggregate (order-123, account-9). A command loads (or snapshots) the stream, checks invariants, appends new events. Readers usually query a CQRS projection, not the raw log.

Why it matters

Sagas and audits want history: not just that the balance is 40, but that it was 90, then a refund, then a chargeback. Ledgers, bookings, and workflow engines already think this way.

Interviewers distinguish this from "we publish Kafka events." Publishing events is notification. Event sourcing means if you lose the events, you lose the business. Kafka can be the store; a Postgres events table can too. The rule is: the log is authoritative, the table of "current orders" is a projection.

How it works

  1. Command comes in (ShipOrder).

  2. Load aggregate: replay events, or load a snapshot plus events after it.

  3. Decide: if already shipped, ignore or error (idempotency).

  4. Append OrderShipped with a stream version (optimistic locking on the log).

  5. Projectors update read models (CQRS). They subscribe to the log or to CDC of the events table.

Optimistic locking is natural: INSERT ... WHERE stream_version = $n. Two concurrent commands, one wins, one retries — post 43 on a stream.

Snapshots are optional performance, not truth. Wrong snapshot code poisons every replay until you fix it and rebuild.

A simple example

A bank account stream: Opened, Deposited(100), Withdrawn(30). Balance 70 is folded. You never UPDATE accounts SET balance = 70 as the source of truth. A fraud query can replay "all withdrawals last night." A CQRS view serves the mobile app balance with a few milliseconds of lag.

Stripe's objects plus an events API are spiritually close: you reason in events even if their public API also shows current state.

Common mistakes

Event sourcing the whole company. User profiles and CMS pages want current state. Use it where the history is the product.

Mutable events. "We will just fix event 400." Then every projection must know about the lie. Prefer new compensating events.

GDPR as an afterthought. "Right to be forgotten" vs append-only logs: encrypt PII, tombstone, or split PII out of the stream.

Replaying forever on every request. Snapshots and read models exist. The log is for writes and rebuilds.

Mixing transport and store. A Kafka topic with 7-day retention is not a ledger.

How this shows up in real systems

  • EventStoreDB, Akka Persistence, Axon, Marten (Postgres): purpose-built or library ES.

  • Kafka as event store: possible with compacted topics / infinite retention and discipline.

  • Accounting ledgers, game item histories, Temporal workflow history: event-sourced in spirit.

  • Git: snapshots + log; useful analogy, not an architecture copy-paste.

Recap

  • Event sourcing: append facts, derive state. Snapshots and CQRS views are caches.

  • Use it when audit and rebuild matter; do not use it as a default ORM.

  • Feeding other systems from a state database without dual writes is CDC — last post in this layer.

Layer 4 · Post 10 of 11

← Previous: CQRS → Next: Change Data Capture

Comments


About Me

DSC_7604.jpg

Hi, I am a software engineer from Bangalore, India. Love spending time on gaming and photography. This website is where I will ocassionally throw what comes to my mind. Hope it is useful or at least entertaining to you. :)

 

  • Instagram
  • Facebook
  • Twitter
  • LinkedIn
  • YouTube
  • 500px

© 2023 by Going Places. Proudly created with Wix.com

bottom of page