Quick Summary — TL;DR
Event-driven architecture (EDA) is a software design pattern where components communicate by emitting and reacting to events rather than calling each other directly. When something happens in one service — a user signs up, an order is placed, a payment fails — it publishes an event. Other services that care about that event receive it and react independently.
The distinction between events and commands is fundamental:
OrderPlaced, PaymentFailed, UserSignedUp. The producer doesn't know or care who reacts to it.SendEmail, ChargeCard, GenerateReport. The sender expects a specific service to handle it.Events are facts. Commands are requests. In event-driven architecture, services publish facts and let interested parties decide what to do with them.
Any service that emits events when its state changes. An e-commerce service produces OrderPlaced events. A payment service produces PaymentSucceeded and PaymentFailed events. Producers don't know who's listening.
Services that subscribe to events and react to them. An email service listens for OrderPlaced events and sends confirmation emails. An inventory service listens for the same event and decrements stock. Each consumer handles the event independently.
The infrastructure that routes events from producers to consumers. This could be a message queue (RabbitMQ, SQS), a streaming platform (Kafka, Kinesis), or a webhook delivery system. The broker handles delivery, ordering, and retry logic so producers and consumers don't have to coordinate directly.
Producers publish events to a topic. Consumers subscribe to topics they care about. One event can trigger multiple consumers. This is the most common EDA pattern and is exactly how webhooks work: the provider publishes events, and every registered endpoint is a subscriber.
Instead of storing the current state of an entity, you store every event that changed it. The current state is derived by replaying the event history. An order's state isn't a row with status = 'shipped' — it's the sequence OrderPlaced, PaymentProcessed, OrderShipped. This gives you a complete audit trail and the ability to reconstruct state at any point in time.
Separate the write model (handles commands, produces events) from the read model (built from events, optimized for queries). This is often paired with event sourcing. Writes go to an event store; reads come from projections built by consuming those events.
| Property | Request-driven | Event-driven |
|---|---|---|
| Communication | Synchronous (request/response) | Asynchronous (fire and react) |
| Coupling | Tight (caller knows the callee) | Loose (producer doesn't know consumers) |
| Scaling | Both sides must be available | Producer and consumers scale independently |
| Failure handling | Caller must handle callee failures | Broker handles delivery and retries |
| Consistency | Immediate (strong) | Eventual |
| Debugging | Straightforward (follow the call stack) | Harder (events flow through multiple systems) |
Event-driven architecture is a design pattern where services communicate by publishing and consuming events rather than making direct API calls. When something happens in one service, it emits an event. Other services that care about that event receive it and react independently, without the producer needing to know about them.
In request-driven architecture, Service A directly calls Service B and waits for a response (synchronous). In event-driven architecture, Service A publishes an event and moves on — it doesn't know or care which services consume it (asynchronous). Request-driven is simpler and provides immediate consistency. Event-driven provides loose coupling and independent scaling at the cost of eventual consistency.
Webhooks are event-driven architecture over HTTP. The provider (producer) publishes events by sending HTTP POST requests to registered URLs (consumers). The webhook registration is the subscription. This is pub/sub using HTTP as the transport, which is why webhook systems need the same reliability patterns: retries, idempotency, and dead letter handling.
Event-driven systems rely on webhooks to push events to external consumers and background jobs to process events asynchronously. Events flow through job queues where they're processed with retry policies and routed to dead letter queues when processing fails. Making event consumers idempotent is essential, since events may be delivered more than once.
Recuro handles cron scheduling, retries, alerts, and execution logs -- so you can focus on building your product.
No credit card required