What Is Event-Driven Architecture?

In a traditional system, services call each other: the order service calls payments, then inventory, then email. Each call waits for the next, and each service must know about all the others.

In an event-driven architecture (EDA), services announce what happened instead: "OrderPlaced." Anyone who cares listens and reacts. The order service doesn't know or care who's listening.

That one change, from "tell others what to do" to "announce what happened," reshapes how systems scale, fail and evolve.


🎯 Quick Answer (30-Second Read)

  • An event is a fact about the past: OrderPlaced, PaymentFailed, UserSignedUp.
  • Producers publish events to a broker (Kafka, RabbitMQ, SNS/SQS, EventBridge). Consumers subscribe and react independently.
  • Benefits: loose coupling, easy to add new features, spikes absorbed by the broker, better resilience.
  • Costs: eventual consistency, harder debugging, duplicate and out-of-order events, and multi-step processes needing sagas.
  • Use it when many parts of a system react to the same things. Avoid it for simple CRUD apps.

Request-Driven vs Event-Driven

Request-driven
Order service calls Payment, Inventory, Email and Analytics in turn. Adding "loyalty points" means changing the order service. If Email is down, the order may fail.
Event-driven
Order service publishes OrderPlaced. Each service subscribes. Adding loyalty points means a new subscriber, with no change to the order service. If Email is down, its events wait.
flowchart LR OS["Order service"] -->|"OrderPlaced"| BUS[["Event broker
(Kafka, EventBridge...)"]] BUS --> PAY["Payments"] BUS --> INV["Inventory"] BUS --> EM["Email"] BUS --> AN["Analytics"] BUS -.->|"added later,
no changes upstream"| LOY["Loyalty points"] PAY -->|"PaymentCaptured"| BUS INV -->|"StockReserved"| BUS

Events vs Commands

Command Event
Tense Future: "ReserveStock" Past: "StockReserved"
Intent Asks one specific service to do something States a fact; anyone may react
Can be rejected? Yes No, it already happened
Receivers Exactly one Zero, one or many

Naming events in the past tense is a simple habit that keeps the design honest.


Three Event Styles

  1. Event notification: a thin event, "Order 981 was placed." Consumers call back for details if they need them. Simple, but creates follow-up traffic.
  2. Event-carried state transfer: the event includes the data consumers need (items, amount, address). Consumers don't call back, so services stay independent even if the producer is down.
  3. Event sourcing: the events are the database. Instead of storing current state, you store every event, and state is rebuilt by replaying them. Great for audit trails (ledgers, banking), but adds real complexity.

Multi-Step Workflows: Sagas

Without a single database transaction across services, how do you handle "charge payment, reserve stock, book delivery," where any step can fail? A saga: a chain of local steps, each with a compensating action if a later step fails.

sequenceDiagram participant O as Order participant P as Payments participant I as Inventory O->>P: OrderPlaced P-->>O: PaymentCaptured O->>I: (event) reserve stock I-->>O: StockUnavailable ❌ O->>P: RefundRequested (compensation) P-->>O: PaymentRefunded Note over O: Order marked as cancelled

Two styles:

  • Choreography: each service reacts to events and publishes its own. No central controller, but the overall flow can be hard to see.
  • Orchestration: a coordinator tells each service what to do next. Easier to follow and monitor, at the cost of a central component.

The Hard Parts

Watch out: most brokers deliver at least once, events can arrive out of order, and consumers lag behind. Your users may see "order placed" before "payment confirmed" updates everywhere.
  • Idempotent consumers: processing the same event twice must be safe (Idempotency Explained)
  • Ordering: if order matters, partition events by a key (e.g. order ID) so related events stay in sequence
  • Schema evolution: add fields, don't rename or remove them; use a schema registry for big systems
  • The outbox pattern: write the database change and the event to an "outbox" table in one transaction, then publish from it, so you never update the DB but lose the event
  • Tracing: add correlation IDs to every event so you can follow one order across services
  • Dead letter queues for events that keep failing

When to Use It (and When Not To)

Good fit Poor fit
Many services react to the same business events A small app with a single database
Spiky workloads that need buffering Operations needing an immediate, consistent answer
Audit trails and analytics pipelines Teams without monitoring and tracing in place
Integrating with external systems (webhooks) Simple CRUD screens

Frequently Asked Questions

What is an example of event-driven architecture?

An e-commerce site where the order service publishes an OrderPlaced event, and separate payment, inventory, email and analytics services each react to it independently. New features, like loyalty points, can be added as new subscribers without changing the order service.

Is event-driven architecture the same as microservices?

No. Microservices describe splitting a system into independently deployable services. Event-driven architecture describes how components communicate, by publishing and reacting to events. Many microservice systems use events, but microservices can also communicate through direct API calls.

What is the difference between event sourcing and event-driven architecture?

Event-driven architecture is about services communicating through events. Event sourcing is a storage approach where you persist every event and rebuild state by replaying them. You can use event-driven communication without event sourcing, and most systems do.


Conclusion

Event-driven architecture lets services announce facts instead of calling each other, which makes systems more decoupled, extensible and resilient to spikes. The trade-off is eventual consistency and more complexity: you need idempotent consumers, careful ordering, the outbox pattern, sagas for multi-step workflows, and good tracing.


Sources

Last verified: 2 November 2026.


Related reads: Message Queue Explained · Microservices Architecture Explained · Idempotency Explained · Notification System Design

I write about system design and how real products are built. Follow on LinkedIn or X, or invite me to speak.