Lab 10: Event Sourcing

Time: 60 minutes | Level: Architect | Docker: docker run -it --rm php:8.3-cli bash

Overview

Event Sourcing stores the full history of state changes as an immutable sequence of events. The current state is derived by replaying events. This lab implements a complete Event Sourcing system with SQLite, aggregates, projections, and snapshots.


Step 1: Core Concepts

Traditional CRUD:         Event Sourcing:
┌──────────────┐          ┌─────────────────────────────────────────┐
│ orders table │          │ events table                            │
│ id=1         │    vs    │ OrderCreated {total:100}                │
│ status=paid  │          │ ItemAdded    {sku:ABC, qty:2}           │
│ total=100    │          │ PaymentReceived {amount:100}            │
│ shipped=true │          │ OrderShipped {tracking:TRK999}          │
└──────────────┘          └─────────────────────────────────────────┘
                          Current state = replay all events

Key principles:

  • Events are immutable (append-only)

  • Current state = fold over events

  • Events are named in past tense (OrderCreated, ItemAdded)

  • Each event has aggregate_id and version

  • Projections build read models from events


Step 2: Domain Events


Step 3: EventStore with SQLite


Step 4: Aggregate Root


Step 5: Repository & Full Demo

📸 Verified Output:


Step 6: Projections (Read Models)


Step 7: Snapshots


Step 8: Capstone — Full Event Sourcing Demo

📸 Verified Output:


Summary

Concept
Implementation
Notes

Domain Event

abstract class DomainEvent

Immutable, has aggregateId + version

Event Store

SQLite append-only table

UNIQUE on (aggregate_id, version)

Aggregate

AggregateRoot + recordThat()

Commands produce events

Apply

on{EventName}() methods

Mutate state from events

Repository

save/findById

Persist and reconstitute aggregates

Projection

Event handlers → read model

Rebuild from event stream

Snapshot

Store state at version N

Optimize loading long streams

Replay

Iterate events + apply

Rebuild any state at any point

Optimistic lock

UNIQUE constraint on version

Prevent concurrent writes

Event bus

Publish events to projections

Fan-out to multiple read models

Last updated