Event Sourcing
Persists state as an immutable sequence of events rather than the current state.
Context
Full auditing, replay of production bugs, derived read models, regulated systems (banking).
Problem
Saving only the current state loses the why of the change.
Solution
Each change is an event (OrderPlaced, OrderPaid). State is reconstructed by folding the events.
#Example in C#
public abstract record DomainEvent(DateTime At);
public record OrderPlaced(Guid Id, decimal Total, DateTime At) : DomainEvent(At);
public record OrderPaid(Guid Id, DateTime At) : DomainEvent(At);
public class Order
{
public Guid Id { get; private set; }
public decimal Total { get; private set; }
public bool Paid { get; private set; }
public static Order Replay(IEnumerable<DomainEvent> events)
{
var order = new Order();
foreach (var e in events) order.Apply(e);
return order;
}
private void Apply(DomainEvent e)
{
switch (e)
{
case OrderPlaced p: Id = p.Id; Total = p.Total; break;
case OrderPaid: Paid = true; break;
}
}
}When NOT to use it
- If you don't need deep auditing or replay: it adds enormous complexity.
- If event schema migration is not planned: you'll drown.
Tradeoffs
| Pro | Con |
|---|---|
| Perfect auditing + replay | Migration of versioned events is difficult |
| Fits with CQRS and projections | Snapshots needed for entities with many events |
#extra #events #audit