Event-Driven Architecture
In an event-driven architecture, parts of the system communicate by emitting and reacting to events instead of calling each other directly. An event is a fact that already happened, like “OrderPlaced” or “PaymentReceived”. This decouples senders from receivers and lets systems work asynchronously.
Producers and consumers
A producer publishes an event without knowing who will handle it. A consumer subscribes and reacts. A broker (a queue or message bus) sits in the middle.
Producer --> [ Broker / Queue ] --> Consumer A
--> Consumer B
The producer fires and forgets. Consumers process at their own pace.
Queues vs pub/sub
There are two common patterns.
Queue (work distribution):
Producer -> [ msg1 msg2 msg3 ] -> one worker takes each message
Pub/Sub (broadcast):
Producer -> Topic -> Subscriber 1
-> Subscriber 2
-> Subscriber 3
With a queue, each message is handled once by one worker, good for spreading work. With pub/sub, every subscriber gets a copy, good for notifying many systems.
A concrete flow
User places order
-> "OrderPlaced" event published
-> Inventory service reserves stock
-> Email service sends confirmation
-> Analytics service records the sale
The order service does not call the other three. It just announces what happened.
Advantages
- Loose coupling: services evolve independently.
- Resilience: if a consumer is down, messages wait in the queue.
- Scalability: add more consumers to handle load.
- Easy to add new reactions without touching the producer.
Disadvantages
- Harder to trace a flow across many services.
- Eventual consistency: things update slightly later, not instantly.
- You must handle duplicate and out-of-order messages.
- More moving parts to operate and monitor.
When to use it
Choose event-driven design when actions naturally trigger side effects, when you need to decouple teams, or when spikes in load require buffering. Avoid it for simple request/response flows where a direct call is clearer.