Why 100% Synchronous Communication Can Destroy Your Microservices Architecture
If you use 100% synchronous communication (REST/OpenFeign/gRPC) between all microservices, the system will work initially, but as traffic grows several problems appear. Let's take an e-commerce example. Exampleβ¦
If you use 100% synchronous communication (REST/OpenFeign/gRPC) between all microservices, the system will work initially, but as traffic grows several problems appear.
Let’s take an e-commerce example.
Example Flow
User places an order.
Order Service
β
Inventory Service
β
Payment Service
β
Notification Service
β
Shipping Service
Every service waits for the next service’s response.
1. Increased Response Time
Suppose:
- Inventory = 200 ms
- Payment = 500 ms
- Notification = 300 ms
- Shipping = 400 ms
Total:
200 + 500 + 300 + 400
= 1400 ms
User waits 1.4 seconds.
If one service becomes slow:
Payment = 5 sec
Entire request takes 5+ seconds.
Problem
One slow service makes the whole application slow.
2. Service Dependency
Suppose Payment Service is down.
Order β Payment β
Order creation fails.
Even though:
- Product exists
- Inventory exists
User cannot place an order.
Problem
One service failure causes business failure.
3. Cascading Failure
Imagine:
Order Service
β
Inventory Service
β
Payment Service
Payment becomes slow.
Inventory threads are waiting.
Order threads are waiting.
API Gateway threads are waiting.
Soon:
Thread Pool Full
Now every request starts failing.
This is called:
Cascading Failure
One service failure spreads across the system.
4. Tight Coupling
Order Service knows:
- Payment API
- Inventory API
- Shipping API
If Payment API changes:
POST /pay
to
POST /payments/create
Order Service must change.
Problem
Services become dependent on each other.
5. Reduced Availability
Suppose each service has 99% availability.
Order = 99%
Inventory = 99%
Payment = 99%
Shipping = 99%
Combined availability:
0.99 Γ 0.99 Γ 0.99 Γ 0.99
β 96%
Even though each service is highly available, the overall business flow becomes less available.
6. Poor Scalability
Suddenly:
10,000 orders/min
Order Service calls Payment synchronously.
Payment cannot handle traffic.
Now:
Order Service blocked
You must scale both services together.
Problem
Independent scaling becomes difficult.
7. Retry Storm
Suppose Payment Service is slow.
Order Service retries:
Retry 1
Retry 2
Retry 3
1000 requests become:
1000 Γ 3
=
3000 requests
Payment Service gets overloaded even more.
Problem
Retries can kill an already struggling service.
8. Network Dependency
In monolith:
paymentService.process();
is an in-memory call.
In microservices:
http://payment-service/pay
Network is involved.
Possible failures:
- Timeout
- DNS issue
- Connection reset
- SSL issue
- Service unavailable
Problem
Distributed systems are inherently less reliable.
When Should Async (Kafka/RabbitMQ) Be Used?
Good candidates:
Order Created Event
Order Created
β
Kafka
β
Inventory
Notification
Analytics
Loyalty Points
Email
Order Service does not wait.
User immediately gets:
Order Placed Successfully
Other services process later.
Email Sending
Bad:
Order β Email Service
(wait)
Good:
Order Created Event
β
Kafka
β
Email Service
User doesn’t care if email arrives 2 seconds later.
Analytics
Bad:
Order β Analytics
(wait)
Good:
Order Created Event
β
Kafka
β
Analytics
Analytics processing should never block order placement.
Interview Answer
If an interviewer asks:
What problems arise if all microservices communicate synchronously?
You can answer:
Using only synchronous communication creates service dependency, higher latency, cascading failures, reduced availability, poor scalability, thread blocking, and retry storms. If one downstream service becomes slow or unavailable, the entire request chain can fail. Therefore, critical request-response operations use synchronous communication, while event-driven operations such as notifications, analytics, audit logging, and inventory updates are often handled asynchronously using Kafka or other message brokers.
A mature microservice architecture usually uses both:
- Synchronous (REST/OpenFeign/gRPC) for immediate responses.
- Asynchronous (Kafka/RabbitMQ) for events and background processing.