Event-Driven Architecture
A design pattern where services communicate by producing and consuming events rather than making direct calls. Promotes loose coupling and asynchronous processing.
What is Event-Driven Architecture?
In short
Event-driven architecture is a design style where services communicate by emitting and reacting to events (records of something that happened, like "OrderPlaced") instead of calling each other directly. A producer writes an event to a broker such as Kafka or a queue, and any number of consumers read it and act on their own time, which keeps services loosely coupled and lets work happen asynchronously.
What it actually is
In a normal request-response system, service A calls service B directly and waits for an answer. If B is down or slow, A is stuck. Event-driven architecture flips this around. Instead of calling anyone, a service just announces a fact: "Order 4821 was placed." That announcement is an event. It is an immutable record of something that already happened, written in the past tense.
The service that emits the event is the producer. It does not know or care who is listening. Other services, the consumers, subscribe to the kinds of events they care about and react when one arrives. An OrderPlaced event might trigger the payment service, the inventory service, the email service, and an analytics pipeline, all independently, none of them aware of each other.
Sitting between producers and consumers is a broker or event bus, such as Apache Kafka, RabbitMQ, AWS EventBridge, or NATS. The producer hands the event to the broker and moves on. The broker holds the event and delivers it to interested consumers. This indirection is the whole point: nobody has a hardcoded address for anybody else.
How it works under the hood
There are two common shapes. In the publish-subscribe model, every subscriber gets its own copy of every event on a topic. Kafka does this with consumer groups, where each group reads the full stream independently and tracks its own offset (its position in the log). In the queue model, used by RabbitMQ or SQS, competing consumers pull from one queue and each message is handled by exactly one of them, which is how you spread load across workers.
Brokers like Kafka store events as an append-only log on disk, partitioned for parallelism and replicated across brokers for durability. Events stay around for a configured retention window (often 7 days, sometimes forever), so a brand-new consumer can replay history from the beginning. That replayability is a feature you do not get from a plain function call.
Delivery is usually at-least-once, meaning a consumer might see the same event twice if a network hiccup causes a redelivery. Because of that, consumers are written to be idempotent: processing OrderPlaced for order 4821 a second time must not charge the customer twice. Teams handle this with deduplication keys, upserts, or by checking whether the work was already done.
When to use it and the trade-offs
Reach for event-driven architecture when one action needs to fan out to many independent reactions, when you want services to scale and fail independently, or when you need to absorb traffic spikes by buffering work in a broker instead of overloading a database. It shines in order processing, payments, notifications, audit logging, and streaming analytics.
The cost is that the system becomes harder to reason about. There is no single stack trace for a request that crosses five services through a broker. You trade synchronous certainty for eventual consistency: right after an order is placed, the inventory count may be stale for a few hundred milliseconds until the consumer catches up. Debugging means correlating events across services using trace IDs and tools like distributed tracing.
You also inherit real operational work: handling duplicate and out-of-order events, building dead-letter queues for events that keep failing, versioning event schemas so an old consumer does not break when a producer adds a field, and running the broker itself. For a small app with simple flows, a direct REST or gRPC call is simpler and you should not over-engineer it.
A concrete example
Picture an e-commerce checkout. The user clicks Pay. The order service does one thing: it writes an OrderPlaced event to a Kafka topic and immediately returns a confirmation to the browser. The user sees "Order received" in well under a second.
Behind the scenes, four consumers are subscribed to that topic. The payment service charges the card. The inventory service decrements stock. The shipping service creates a fulfillment task. The email service sends a receipt. If the email service is briefly down, Kafka holds the event and redelivers it when the service comes back, so the receipt is delayed but never lost.
Compare that to the synchronous version, where the order endpoint would call all four services in a row and the user would wait for the slowest one, and a single failure would fail the whole checkout. The event-driven version is faster for the user, more resilient, and lets each team deploy and scale their service on its own schedule.
Where it is used in production
Uber
Runs trillions of messages a day through Apache Kafka so trip events fan out to pricing, dispatch, fraud, and analytics services independently.
Netflix
Uses event streams for its Keystone pipeline, emitting playback and UI events that drive recommendations, monitoring, and billing without tight coupling.
AWS EventBridge
A managed event bus that lets services and SaaS apps publish events and route them to Lambda, queues, and other targets via rules.
Shopify
Emits webhooks and internal events such as orders/create so merchant apps and downstream systems react to store activity asynchronously.
Frequently asked questions
- What is the difference between an event and a message or command?
- An event is a statement of fact about the past (OrderPlaced) with no expectation of a reply, and the producer does not know who consumes it. A command is a request to do something specific (ChargeCard) aimed at a known handler. Message is the generic envelope that carries either one over a broker.
- Is event-driven architecture the same as microservices?
- No. Microservices is about splitting an application into small independently deployed services. Event-driven architecture is one way those services can talk to each other. You can build microservices that call each other synchronously over REST, and you can build event-driven flows inside a single monolith. They pair well but are separate ideas.
- How do you avoid processing the same event twice?
- Most brokers guarantee at-least-once delivery, so duplicates happen. Make consumers idempotent by using a unique event ID to deduplicate, performing upserts instead of blind inserts, or recording which events have already been handled before doing the work. The goal is that reprocessing the same event produces the same end state.
- What is eventual consistency in this context?
- Because consumers process events asynchronously, different services are briefly out of sync. Right after an order event, the inventory service may not have decremented stock yet. The system becomes consistent once all consumers catch up, usually within milliseconds. You design around this by not requiring every read to see the latest write instantly.
- When should I not use event-driven architecture?
- Avoid it when you need an immediate synchronous answer (like a login check or a balance lookup), when the flow is simple and a direct call is clearer, or when your team cannot yet operate a broker and handle duplicates, ordering, and schema versioning. Adding a broker to a small app usually adds more complexity than it removes.
Learn Event-Driven Architecture hands-on
This page explains the idea. The full lesson lets you step through the ring as servers join and leave, read the implementation, and check yourself with a quiz. It is one of 760+ lessons in the System Design Masterclass, from your first API call to distributed consensus. Eleven Foundation lessons are free, no signup. Lifetime access is ₹499 in India or $7.99 worldwide, one payment, no subscription.
Related lessons
Lessons that touch on Event-Driven Architecture as part of a larger topic.
See also
Related glossary terms you might want to look up next.
Pub/Sub
A messaging pattern where publishers send messages to topics, and subscribers receive messages from topics they care about. Publishers don't know who's listening.
Kafka
A distributed event streaming platform that handles millions of events per second. Used by LinkedIn, Netflix, and Uber for real-time data pipelines.
Event Sourcing
Storing every state change as an immutable event instead of just the current state. You can rebuild any past state by replaying events.
Message Queue
A buffer that stores messages between producers and consumers. Messages are processed one by one, in order. Think of it as a to-do list for your services.
Webhook
An HTTP callback triggered by an event. Instead of polling for updates, the source system pushes a notification to your URL when something happens.
Kafka Topic
A named feed or category to which producers publish records. Topics are split into partitions for parallelism, and each partition is an ordered, immutable log.