We use analytics cookies.We use cookies to analyze site traffic and improve your experience.
Loading...
System Design Masterclass · Messaging Event Systems
Free preview: the first 2 parts of this 6-part lesson.
Already bought the course? Sign in to read the whole lesson.
this lesson is part of
System Design Masterclass
Unlock this lesson and the 751 other paid lessons
$25 once, by PayPal
See the System Design courseread the rest of this lesson in
System Design Masterclass
Unlock this lesson and the 751 other paid lessons
$25 once, by PayPal
See the System Design coursein Messaging Event Systems
This lesson is part of the full System Design Masterclass. Unlock it along with 769 other lessons for a one-time payment.
One-time payment by card or PayPal
Get Lifetime AccessOne-time payment: UPI, card or netbanking
Get Lifetime Access18 Foundation lessons are free, no payment needed. Try them now
It is easy and good
“It is really nice and good Please join the course”
You walk up to a coffee counter. "One latte, please." The barista nods, makes the drink, and hands it to you. You asked for something, you waited, and you got a response.
That is request-response. It is so natural that you do not think of it as a "pattern." It is just how conversations work. One party sends a message, the other processes it and sends a reply, and the first party uses that reply to continue.
Every API call is request-response. Every database query. Every function call. It is the default mode of communication in software, and for good reason: it is simple, predictable, and the caller gets immediate feedback about whether the operation succeeded or failed.
The catch is synchronous waiting. While the caller waits for the response, it is blocked. It consumes a thread, a connection, or a coroutine. At small scale, this is irrelevant. At massive scale, millions of blocked threads waiting for slow backends can bring the entire system to its knees. Google engineers have measured this: when a call chain is 5 hops deep and each hop takes 50ms, the total request takes 250ms minimum, and a single slow hop makes every upstream caller wait.
Understanding when request-response is the right choice, and when you need to break out of it, is the difference between a system that scales and one that collapses under load.
Request-response is deceptively simple, but there are important properties to understand:
Synchronous coupling. The caller is blocked until the response arrives. If the responder is slow or down, the caller is stuck. A thread or connection is consumed for the entire duration.
Temporal coupling. Both parties must be available at the same time. If the server is down when the client sends the request, the request fails immediately. There is no buffer, no retry, no queue between them.
Direct addressing. The caller must know exactly where to send the request: the URL, the service name, the IP address. There is no intermediary to discover or route.
Client --[request]--> Server
Client <--[response]-- Server
Timeline:
Client: |--send--|--------wait--------|--process response--|
Server: |--receive--|--work--|--send response--|
Variations:
| Variant | Blocking? | Transport | Example |
|---|---|---|---|
| request/response | Yes (until response) | HTTP | call |
| RPC (, Thrift) | Yes | , HTTP/2 | Service-to-service call |
| Database query | Yes | TCP | SELECT FROM users |
| Synchronous queue RPC | Yes (via correlation ID) | RabbitMQ RPC pattern |
The synchronous queue variant is interesting. You send a message to a queue and then block waiting for a response on a reply queue. It is still request-response semantics, but decoupled by a message broker. RabbitMQ's RPC tutorial demonstrates this pattern, and it leads directly to the request-reply pattern covered in the next lesson.