Event Sourcing — State as an Immutable Event Log
Store state as an append-only sequence of events; derive current state by replaying them.
When to use
- Full audit log required
- Temporal queries needed (what was the state at time T?)
- Undo/replay functionality
Tradeoffs
- Event schema evolution is hard (can't change past events)
- Replay can be slow without snapshots for large streams
- Go
- Python
type Event struct {
Type string
Payload any
}
var store []Event
func append(e Event) { store = append(store, e) }
func replay(events []Event) Order {
var o Order
for _, e := range events {
switch e.Type {
case "OrderPlaced": o.Status = "placed"
case "OrderShipped": o.Status = "shipped"
}
}
return o
}
from dataclasses import dataclass, field
from typing import Any
@dataclass
class Event:
type: str
payload: Any
store: list[Event] = []
def append_event(e: Event) -> None:
store.append(e)
def replay(events: list[Event]) -> dict:
state: dict = {}
for e in events:
if e.type == "OrderPlaced":
state["status"] = "placed"
elif e.type == "OrderShipped":
state["status"] = "shipped"
return state
Gotcha: Never mutate past events. Create a new corrective event (
OrderCancellationCorrected) instead.