Intermediate28 min read· Topic 5.5

Event-driven architecture (EDA)

Event sourcing, CQRS, Saga pattern, Outbox pattern, Change Data Capture

Key Takeaways

  • 1
    Event sourcing: store state as a sequence of events, not current state — enables time travel and audit
  • 2
    CQRS: separate read and write models — optimize each independently
  • 3
    Saga pattern: coordinate distributed transactions across microservices without 2PC
  • 4
    Outbox pattern: reliably publish events with database transactions (prevents dual-write problem)

Beyond Simple Messaging

Event-Driven Architecture (EDA) is a paradigm where the flow of the program is determined by events — user actions, sensor data, messages from other systems. It goes beyond simple message queues to encompass patterns like event sourcing, CQRS, and sagas that fundamentally change how you design systems.

Core EDA Patterns

Instead of storing current state (User.balance = 100), store every event that led to that state: BalanceDeposited(50), BalanceDeposited(80), BalanceWithdrawn(30).

Current state is derived by replaying events. You can 'time travel' to any point. Perfect audit log. But adds complexity — querying current state requires replay or materialized views.

Separate the write model (commands) from the read model (queries). Writes go to a normalized database. Reads come from denormalized views optimized for specific queries.

Enables: different databases for reads vs writes. Highly optimized read views. Independent scaling.

Use when: read and write patterns are very different. Read scale >> write scale.

A saga is a sequence of local transactions across services. Each step has a compensating transaction (undo) in case of failure.

Example: Place order → Reserve inventory → Charge payment → (if payment fails) → Release inventory → Cancel order.

Types: Choreography (events between services) vs Orchestration (central coordinator).

Problem: Writing to DB AND publishing to queue is a dual write — if one fails, they're inconsistent.

Solution: Write event to an 'outbox' table in the same DB transaction. A separate process reads the outbox and publishes to the message queue.

Guarantees atomicity between state change and event publication.

⚠️EDA Complexity Warning
Event-driven architecture adds significant complexity: eventual consistency, event ordering, idempotency, debugging distributed event chains. Don't use EDA because it's trendy — use it when you genuinely need decoupled, scalable, event-based processing.

Advantages

  • Loose coupling between services
  • Event sourcing provides a complete audit trail
  • CQRS enables optimized read/write models
  • Saga pattern handles distributed transactions

Disadvantages

  • Eventual consistency is hard to reason about
  • Debugging event chains is complex
  • Event sourcing adds replay/projection overhead
  • Over-engineering risk for simple systems

🧪 Test Your Understanding

Knowledge Check1/1

What problem does the Outbox Pattern solve?