Advanced15 min

Event-Driven Architecture

Build systems around facts that happened, not commands you issue.

By the end of this lesson, design services that communicate through events and understand the coupling trade-off.

How deep?
How the pieces actually move.

In event-driven architecture, services publish events — immutable statements that something happened (OrderPlaced, PaymentCaptured) — and other services react. Instead of a service commanding others ('reserve inventory'), it announces a fact and interested services respond on their own. This inverts dependencies: the producer doesn't know who consumes.

First, the whole system

First, see the whole system. Then we’ll open it up.

Publish facts, react independently

Publish facts, react independently

  1. The order service publishes OrderPlaced to an event bus; inventory, payment, and notification services each react independently.
flowchart LR
  order[Order service] -->|OrderPlaced| bus[(Event bus)]
  bus --> inv[Inventory service]
  bus --> pay[Payment service]
  bus --> notify[Notification service]

Flavors range from event notification (thin events, consumers fetch details), through event-carried state transfer (fat events carry the data consumers need), to event sourcing (the event log *is* the source of truth; current state is a fold over events). Events pair with the outbox for reliable publishing and with sagas for cross-service workflows.

Operational complexity

Event-driven design buys loose coupling, independent scaling, and auditability, at the cost of eventual consistency, harder end-to-end tracing (the flow is emergent), and the operational weight of a broker. Synchronous request/response is easier to follow but tightly couples caller to callee.

Abstraction leak

This is where the abstraction starts leaking.

There is no global 'now' in an event-driven system. Consumers see facts at different times and in partition-local order. Any logic that assumes all services share the same up-to-the-millisecond view of the world will produce subtle inconsistencies.

How does publishing an event differ from calling a command?

An event states a fact that happened and the producer doesn't know or care who reacts; a command tells a specific service to do something, coupling caller to callee.

Event-driven systems still expose synchronous APIs at their edges. How do you design and integrate those APIs well?

Next: APIs & Integration →