Event-Driven Architecture
Architecture built around events: event producers, consumers, brokers, event schemas, event sourcing integration, and reactive systems.
What Is Event-Driven Architecture?
Event-Driven Architecture (EDA) structures a system around the production, detection, and consumption of events — facts about something that happened in the system. Rather than components calling each other directly (tight coupling), components emit events that others can subscribe to independently. This decouples producers and consumers in time, space, and logic.
Companies like Uber, LinkedIn, and Airbnb use event-driven systems extensively. Uber's driver location updates flow as events; LinkedIn's feed updates are events from connections; Airbnb's booking pipeline is event-driven from search through payment confirmation.
Core Components
| Component | Role | Examples |
|---|---|---|
| Event Producer | Publishes events when something happens in its domain | Order Service emits `order.placed`, Payment Service emits `payment.processed` |
| Event Broker | Stores and routes events to subscribers; provides durability and replay | Apache Kafka, AWS SNS/SQS, RabbitMQ, Azure Event Hubs |
| Event Consumer | Subscribes to topics and reacts to events | Inventory Service decrements stock, Email Service sends confirmation |
| Event Schema | Defines the structure of the event payload | Avro schema, Protobuf, JSON Schema in a Schema Registry |
Event Types
Not all events are the same. It is important to distinguish between three patterns:
- Event Notification: A thin event that signals something happened. Consumers fetch details if needed. Low coupling, but requires extra round-trip. Example: `{ type: 'order.placed', orderId: 'ord_123' }`.
- Event-Carried State Transfer: The event includes all the data consumers need, avoiding a callback. Higher payload size, but consumers are fully self-sufficient. Example: `{ type: 'order.placed', orderId: 'ord_123', items: [...], total: 49.99 }`.
- Event Sourcing: Events are the source of truth. Instead of storing current state in a database, you store the full sequence of events and reconstruct state by replaying them. Used in financial systems (every transaction is an immutable event).
Choreography vs Orchestration
In event-driven systems, multi-step processes can be coordinated in two ways:
| Choreography | Orchestration | |
|---|---|---|
| How | Each service reacts to events and emits new events; no central controller | A central orchestrator (saga/workflow) tells each service what to do |
| Coupling | Low — services don't know each other | Moderate — orchestrator knows all services |
| Visibility | Hard to trace the overall flow across services | The orchestrator is the single source of truth for the process |
| Failure handling | Complex — compensating events must propagate | Easier — orchestrator manages compensation steps |
| Examples | Order placed → Inventory reacts → ships → Notification reacts | AWS Step Functions, Temporal, Netflix Conductor |
Advantages of Event-Driven Architecture
- Loose temporal coupling: Producer and consumer don't need to be available simultaneously. The broker buffers events.
- Easy fan-out: One event can trigger N consumers without the producer knowing about any of them.
- Audit log for free: If you use Kafka with log compaction or event sourcing, you have a durable, replayable history of everything that happened.
- Resilience: Consumers can fail, recover, and replay events from where they left off (Kafka consumer offsets).
- Scalability: Consumers can scale independently based on their processing backlog.
Challenges and Trade-offs
Eventual Consistency
EDA systems are inherently eventually consistent. When an order is placed, the inventory update happens asynchronously — there is a window where the order is placed but inventory hasn't been decremented yet. Your system must handle this: idempotent consumers, compensating transactions, and clear user-facing messaging about eventual state.
- Event schema evolution: Changing event schemas without breaking consumers requires a Schema Registry (Confluent) and backward/forward compatibility strategies.
- Duplicate events: At-least-once delivery means consumers may receive the same event twice. All consumers must be idempotent — processing the same event twice must not cause double-effects.
- Out-of-order delivery: Events may arrive out of order. Consumers must handle this gracefully or use ordered partitioning.
- Distributed tracing: A user request that fans out to 10 consumers requires correlation IDs and distributed tracing (Jaeger, OpenTelemetry) to debug.
- Debugging complexity: You can no longer step through a linear call stack — the flow is defined implicitly by event subscriptions.
Interview Tip
For any system design with asynchronous workflows (order processing, notification systems, data pipelines), mention event-driven architecture. Key points to hit: (1) decouple via a broker so producers don't block on consumers, (2) consumers must be idempotent for at-least-once delivery, (3) discuss choreography vs orchestration for multi-step workflows, and (4) mention Kafka offsets or SQS visibility timeout for consumer fault tolerance.
Practice this pattern
Design an event-driven e-commerce order processing system