⚡ Event-Driven Architecture
Sync vs Async — When to Use EDA
Understanding when synchronous REST calls create brittleness and when async events save you
Synchronous calls couple services in time — if Service B is slow or down, Service A fails too. Event-driven architecture decouples services temporally: Service A publishes an event and continues, regardless of whether downstream services are running.
Key Concepts
Synchronous = Temporal Coupling
REST/gRPC: caller waits for response. If downstream service takes 2 seconds, caller waits 2 seconds. If it's down, caller fails. Each service's SLA degrades its callers.
Async = Temporal Decoupling
Publisher fires event to broker and continues. Subscriber processes at its own pace. Notification service can be down for hours — events queue up and process when it recovers.
Backpressure Control
Message broker acts as a buffer. During traffic spikes, producers write to broker (fast). Consumers drain at sustainable pace (slow). Without broker, spike hits DB directly.
The Cascading Failure Problem
Imagine an E-Commerce checkout flow. A user clicks 'Buy'. The Order Service creates the order in the database, then makes a **Synchronous HTTP POST** to the Email Service to send a receipt. What happens if the Email Service is experiencing high latency?
- The Order Service HTTP thread blocks, waiting for the Email Service.
- As more users click 'Buy', more threads are blocked in the Order Service.
- Eventually, the Order Service runs out of HTTP threads (Thread Starvation) and crashes.
- Now, users cannot place orders at all—all because the non-critical Email Service was slow. This is a **Cascading Failure**.
Architecture Comparison
Solving the problem with Event-Driven Architecture
By introducing a Message Broker (like Kafka or RabbitMQ), we achieve **Temporal Decoupling**. The Order Service no longer calls the Email Service directly.
- Order Service publishes an `OrderCreated` event to the broker and immediately responds to the client with `200 OK`.
- Even if the Email Service is completely dead, orders continue to process normally.
- The events are safely stored in the Message Broker.
- When the Email Service is restarted hours later, it pulls the accumulated events from the queue and sends the emails.
When to Use Sync vs Async
| Operation Type | Pattern | Example | Reason |
|---|---|---|---|
| User reads data | Sync (REST/gRPC) | GET /product/:id | User expects immediate response |
| User submits order | Sync for ack + Async for processing | POST /order → 202 Accepted | Acknowledge receipt, process downstream async |
| Send confirmation email | Async (Event) | OrderCreated → email queue | Email failure should not fail order creation |
| Inventory deduction | Async Saga | OrderCreated → StockService | Cross-service write coordination |
| Generate invoice PDF | Async (Event) | PaymentCompleted → pdf queue | Background heavy computation |
| Real-time user location | Sync or WebSocket | GET /driver/:id/location | Real-time data requires live connection |
💡
Senior Architect Insight: Use synchronous calls only when you strictly need the response to continue execution. 'Send order confirmation email' does NOT require a synchronous response — fire it as an event. This single rule eliminates 70% of cascading failure scenarios.