| Users / Requests | Synchronous Communication | Asynchronous Communication |
|---|---|---|
| 100 users | Direct request-response calls work well; low latency; simple error handling | Message queues lightly used; delays minimal; easy to manage |
| 10,000 users | Increased latency; some request timeouts; servers start to block waiting for responses | Message queues handle bursts; decoupling improves resilience; some message backlog possible |
| 1 million users | High latency; many blocked threads; servers overwhelmed; cascading failures possible | Queues scale with partitions; consumers scale horizontally; eventual consistency accepted; better fault tolerance |
| 100 million users | System likely fails; synchronous calls cause bottlenecks; scaling very costly | Distributed queues with sharding; multiple consumer groups; complex monitoring; high throughput achievable |
Synchronous vs asynchronous communication in Microservices - Scaling Approaches Compared
Start learning this pattern below
Jump into concepts and practice - no test required
In synchronous communication, the first bottleneck is the application server's thread pool and CPU waiting on remote calls, causing blocked resources and increased latency.
In asynchronous communication, the bottleneck shifts to the message broker's throughput and storage capacity, as it must handle high message volumes reliably.
- Synchronous: Use load balancers and horizontal scaling of services to increase concurrent handling; implement timeouts and retries; introduce caching to reduce calls.
- Asynchronous: Scale message brokers horizontally with partitioning and replication; add more consumers to process queues in parallel; use backpressure and rate limiting; implement dead-letter queues for failures.
- For both, use circuit breakers to prevent cascading failures and improve system resilience.
Assuming 1 million users generating 10 requests per second:
- Total requests: 10 million requests/sec.
- Synchronous servers: Each server handles ~3000 concurrent requests; need ~3300 servers to handle load.
- Message broker: Needs to handle 10 million messages/sec; a single Kafka cluster can handle ~1 million messages/sec, so at least 10 clusters or partitions needed.
- Storage: Message retention for 24 hours at 1 KB per message = ~864 GB storage.
- Network bandwidth: 10 million requests/sec * 1 KB = ~10 GB/s (~80 Gbps), requiring high network capacity.
Start by defining synchronous and asynchronous communication clearly. Discuss pros and cons related to latency, coupling, and fault tolerance. Identify bottlenecks at different scales. Propose scaling strategies specific to each mode. Use real numbers to justify your approach. Show understanding of trade-offs and system resilience.
Your database handles 1000 QPS. Traffic grows 10x. What do you do first?
Answer: Introduce caching and read replicas to reduce load on the database. If still insufficient, consider sharding the database to distribute data and queries across multiple instances.
Practice
Solution
Step 1: Understand synchronous communication
Synchronous communication means the caller waits for the response before moving on.Step 2: Compare options
The caller waits for the response before continuing. matches this definition exactly, while others describe asynchronous or unrelated concepts.Final Answer:
The caller waits for the response before continuing. -> Option AQuick Check:
Synchronous = Wait for reply [OK]
- Confusing synchronous with asynchronous communication
- Thinking synchronous means no waiting
- Assuming message queues are always synchronous
Solution
Step 1: Define asynchronous communication
Asynchronous means the caller sends a request and does not wait; it handles the response later.Step 2: Evaluate options
The caller sends a request and processes the response later. correctly describes this behavior. Options A and D describe synchronous calls, and C is unrelated.Final Answer:
The caller sends a request and processes the response later. -> Option DQuick Check:
Asynchronous = Send and continue [OK]
- Mixing up blocking and non-blocking calls
- Assuming async requires same server
- Thinking async means no response
response = callServiceSync(request)
print("Done")
What will be the output order?Solution
Step 1: Analyze synchronous call behavior
The function callServiceSync waits for the service response before returning.Step 2: Determine print timing
Since the call blocks, "Done" prints only after the response is received.Final Answer:
"Done" prints after the service responds. -> Option BQuick Check:
Synchronous call blocks, then prints [OK]
- Assuming print runs before response
- Confusing sync with async calls
- Expecting errors due to missing async syntax
sendRequestAsync(request)
print("Request sent")
waitForResponse()
But the system blocks until the response arrives. What is the likely mistake?Solution
Step 1: Understand asynchronous call flow
sendRequestAsync should not block, but waitForResponse() forces waiting.Step 2: Identify blocking cause
Calling waitForResponse() immediately after sends blocks the flow, negating async benefits.Final Answer:
Calling waitForResponse() immediately blocks the flow. -> Option CQuick Check:
Immediate wait blocks async [OK]
- Assuming async call is sync
- Misplacing print statement
- Blaming request format instead of flow
Solution
Step 1: Analyze requirements
Immediate confirmation requires waiting for a quick response (synchronous).Step 2: Handle heavy processing
Heavy tasks can be done later without blocking user, so asynchronous fits.Step 3: Match communication patterns
Combining synchronous for confirmation and asynchronous for processing meets both needs efficiently.Final Answer:
Use synchronous communication for confirmation and asynchronous for processing. -> Option AQuick Check:
Immediate reply = sync, heavy work = async [OK]
- Using only sync causes delays
- Using only async delays confirmation
- Reversing sync and async roles
