Skip to content

Event Sourcing Principles

Event sourcing is a pattern where state changes are stored as a sequence of immutable events, rather than maintaining only the current state.

What is Event Sourcing?

In traditional systems, we store the current state of entities in a database. When something changes, we update that state, losing the history of how we got there. Event sourcing takes a different approach: instead of storing just the current state, we store a sequence of events that led to that state.

Think of it like a bank account statement. Instead of just showing your current balance, the statement lists every transaction (deposit, withdrawal) that affected your balance. Your current balance is derived by replaying all those transactions in order.

Key Concepts

Events as First-Class Citizens

Events represent facts that have happened in the past. They are immutable - once an event has occurred, it cannot be changed or deleted. Events have a timestamp and carry data about what happened.

Immutable Event Logs

Events are stored in an append-only log. New events are added to the end, but existing events are never modified. This provides a complete audit trail of everything that has happened in your system.

State Reconstruction

The current state of any entity can be reconstructed by replaying all its events from the beginning. This is like "replaying history" to see how we arrived at the current situation.

Time Travel Debugging

Because we have a complete history, we can reconstruct the state at any point in time. This is invaluable for debugging issues: "What did the order look like when the customer submitted it?"

In This Workshop

We use event sourcing for purchase orders in our e-commerce system. Each order goes through a series of state transitions:

CREATED → PENDING → COMPLETED
              ↓
          SHIPPED → DELIVERED
              ↓
          CANCELLED

Each state transition is represented by an event. The PurchaseOrderStatus enum in our spring-boot-kafka-common module defines these states:

public enum PurchaseOrderStatus {
    CREATED,    // Order received
    PENDING,    // Order being processed
    COMPLETED,  // Order fulfilled
    CANCELLED,  // Order cancelled
    SHIPPED,    // Order dispatched
    DELIVERED   // Order completed
}

When a customer submits an order, we create a PurchaseOrderDTO event with status CREATED and publish it to the purchase-orders Kafka topic. The backend consumer processes this event and updates the order state accordingly.

Benefits of Event Sourcing

  • Complete Audit Trail: Every change is recorded with timestamp and details
  • Debugging Capabilities: Reconstruct past states to understand what happened
  • Temporal Queries: Answer questions like "What was the order status at 3pm yesterday?"
  • Event Replay: Fix bugs by replaying events with corrected logic
  • Multiple Projections: Create different views of the same data for different use cases

Challenges

  • Event Schema Evolution: As your system evolves, event formats must remain backward compatible
  • Storage Growth: Event logs grow continuously and need proper retention policies
  • Complexity: More moving parts compared to traditional CRUD systems
  • Eventual Consistency: State updates are asynchronous, requiring careful handling

Key Takeaways

  • Events are immutable facts that have happened in the system
  • Current state is derived by replaying all events in sequence
  • Enables complete audit trails and time-travel debugging capabilities
  • Schema evolution and storage growth require careful planning