Event Sourcing in production — Borjan Tchakaloff

Learn practical tips for implementing event sourcing in production, including handling projections, domain evolution, concurrent requests, and choosing read models.

Key takeaways
  • Event sourcing captures state changes as a sequence of events rather than storing current state, providing a complete history of changes

  • Aggregates are the smallest addressable units that enforce business rules and invariants - all changes must go through them

  • Separate read and write models (CQRS pattern) - write models enforce business rules while read models/projections optimize for querying

  • When handling projections:

    • Create new projectors rather than modifying existing ones
    • Replay full event history to rebuild projections
    • Consider eventual consistency implications
  • For domain evolution challenges:

    • Fail loudly when encountering unknown events
    • Use upcasting for handling legacy events
    • Consider backwards compatibility when adding new attributes
    • Carefully handle unique constraints and data migrations
  • Production considerations:

    • Use hybrid approach with single-threaded workers for concurrent requests
    • Implement atomic saves for multiple aggregates
    • Plan for projection rebuilds during schema changes
    • Handle duplicate detection based on business requirements
  • Read models can be implemented multiple ways:

    • Django models for simple cases
    • Dedicated structures for complex queries
    • Statistical aggregations
    • Temporal tracking approaches
  • Technical implementation:

    • Events should be immutable truth source
    • Applications coordinate command handling
    • Process applications handle cross-domain coordination
    • Event store manages persistence
  • Keep projections and read models separate from core domain logic

    • Projections can be rebuilt from events
    • Different views can serve different query needs
    • Consider eventual consistency tradeoffs