Decoupling Responses from Requests: Event-Driven Approach | Microservice Architecture — Ep. 26
Traditional client-server communication is based on request-response paradigm:
- send a request
- show loading state and wait
- get the response
- update client state
However, microservice architecture does not go along well with it because of two things:
- multiple network hops (high cumulative latency)
- request-response propagation through service chains
So many requests turn into small distributed workflows.
Consider a simple subscription-based video platform. One frontend and three services: Subscriptions, Payments, Recommendations.
The typical “subscribe” workflow may look like this:
- Client calls Subscriptions.
- Subscriptions calls Payments.
- Payment succeeds.
- Recommendations builds a personalized movie list.
- Client fetches recommendations.
Where does this orchestration live?
- In the frontend? → tight coupling to backend internals
- In a BFF? → centralized coordination and sequential bottlenecks
Both approaches are fragile due to excessive coupling. And if each service talks to each in request-response paradigm, it becomes a tough task under load, having to support hundreds and thousands of open connections.
An alternative is to decouple responses from requests using events. Instead of calling each other and waiting for long responses, services communicate through a message broker:
- Subscriptions emits ‘UserSubscribed’
- Payments consumes it and processes payment
- Payments emits ‘PaymentCompleted’
- Subscriptions and Recommendations react independently
- Recommendations emits ‘RecommendationsReady’
- Some Notifications service may send an email or a live update to the frontend client
With event-driven architecture we achieve three things:
- services no longer keep open connections, waiting only for confirmation from message broker
- if some service breaks, requests are not lost, but can be picked up from the message broker by another service instance
- there is no node concerned with process coordination — coordination complexity is moved to communication space
- the system becomes asynchronous: frontend clients receive immediate feedback and unlock other activities while complex workflows are processed in background
The tradeoff — we lose immediate consistency. The benefit — we gain scalability, resilience, and simple service boundaries. This shift, from waiting for results to reacting to events, is one of the key mindset changes in distributed systems.