System Design Patterns: From Fundamentals to Real Systems
Vote

0% completed

​

Request-Response

  1. The Pattern
  1. What It Gives You
  1. What It Costs
  1. One Question Per Arrow
  1. When Not to Use It
  1. In the Interview
  1. Check Yourself
  1. Related Patterns
  1. TL;DR

1. The Pattern

The caller sends a request and waits until the answer comes back, either a result or an error, before doing anything else.

Most service-to-service communication uses this pattern, which makes it the default choice. The other six patterns in this module are deliberate alternatives to a direct call.

Why does a default pattern require a separate lesson? Engineers who have recently learned about queues and events sometimes introduce them where they are not needed.

In most systems, a simple synchronous call is correct for most traffic. Synchronous means that the caller stops and waits for an answer. Common examples include loading a page, running a search, checking a password, looking up a price, and authorizing a payment.

Use request-response when a user is actively waiting for the result. Adding a queue does not remove that wait.

Request-Response
Request-Response

2. What It Gives You

  1. The answer, immediately. The next line of code can use the returned result. You do not need to design a "we received your request, check back later" state.
  2. Errors arrive where you can handle them. When the call fails, the calling code can retry, display a message, or use a fallback. A failed background job is harder to trace because its failure occurs separately from the request that created it.
  3. Simple debugging. One request follows one path through the system and produces one trace to inspect.

One practical detail has a large effect on performance: opening a new connection is expensive. Each connection begins with TCP and TLS handshakes, which are setup messages that establish and secure the link. These handshakes require one to three network round trips, or around 100 ms across regions.

Connection pooling, also called keep-alive, keeps connections open so later calls can reuse them. Every production HTTP client supports this behavior, but you should confirm that it is enabled.

3. What It Costs

Each individual cost may appear small, but a chain of calls combines them into a larger reliability and latency problem.

Both sides must be up at the same moment. A call fails immediately when the receiving service is unavailable. This dependency on both services being available together is called temporal coupling.

Availability multiplies down a chain. Availability measures the share of time that a service responds correctly. Suppose an endpoint calls 5 services in sequence and each service is available 99.9% of the time. The endpoint succeeds only when all five services succeed: 0.999 x 0.999 x 0.999 x 0.999 x 0.999 = about 99.5%.

Although that percentage appears high, it represents roughly 44 hours of failures per year. Every additional dependency reduces the result further.

Latency adds up. Latency measures how long a call takes to return. Five sequential calls that each require 80 ms take 400 ms in total.

When those five calls are independent, run them in parallel instead of in sequence. The endpoint then waits only for the slowest call, which takes roughly 80 ms. Replacing accidental sequential work with parallel work is often the fastest improvement for a slow endpoint.

Waiting holds resources. A caller keeps a thread or connection occupied while it waits. At 300 requests per second and a 2-second wait, 600 requests remain in progress at any moment, and each one holds a thread.

Request-response therefore needs three protections at scale. A timeout stops waiting after a deadline. Retries repeat calls after brief failures. A circuit breaker stops sending calls to a service that is clearly unavailable. Later lessons examine each protection in detail.

4. One Question Per Arrow

Ask one question before drawing an arrow in a system design.

Does the caller's next step depend on the answer, and is anyone waiting?

When both answers are yes, use a direct call. Otherwise, another communication pattern may be more suitable:

The situationUse
The next step needs the answer, and someone waitsRequest-response (this lesson)
The work can happen laterMessage Queue
Several services need to know something happenedPublish-Subscribe
Another company's system needs to be notifiedWebhooks
Updates flow continuously in one directionServer-Sent Events
Both sides send messages continuouslyBidirectional Streaming

Each alternative introduces a cost, such as a pending state, possible duplicate delivery, or a connection that must be managed. A pending state means that the system accepted the work but has not finished it.

Change patterns because an immediate answer is unnecessary, not because an alternative sounds more advanced.

5. When Not to Use It

Long-running work. Work that takes more than a few seconds should not keep a caller waiting. Accept the job, return a "job started" response immediately, and deliver the result through a queue, status endpoint, or webhook.

Notifying many services about one event. Calling five services separately because each one needs the same order update creates unnecessary coupling. The Publish-Subscribe lesson begins with this problem and publishes the event instead.

Bursty work with relaxed deadlines. Bursty work arrives in sudden spikes. The Message Queue lesson begins with a flash sale that overwhelmed a synchronous pipeline. If nobody is waiting, the work can be processed later.

Chains that have grown too deep. With six synchronous calls in sequence, availability has already fallen and latency has already increased. Shorten the chain, run independent calls in parallel, cache results, or move suitable work to a queue.

Going asynchronous by habit. The reverse mistake is adding Kafka to a search query or making login checks event-driven. The user still needs the answer and must continue waiting, but now the request passes through a message broker, which is a server that stores and forwards messages.

That broker adds latency and duplicate-delivery risk to a path that needs an answer within 200 ms. Asynchronous communication is appropriate when waiting is optional, but it is not automatically better.

6. In the Interview

Interviewers rarely ask about request-response by name. Instead, they examine the synchronous arrows in your diagram and ask, "Why is this a synchronous call?"

A complete answer identifies the dependency: "Checkout cannot continue without the payment result, and the user is waiting. So this stays synchronous, with a timeout, a capped number of retries, and a circuit breaker around it."

The 30-second answer: "Request-response is my default for anything the caller's next step depends on: auth, pricing, payment authorization, every interactive read. I get the answer immediately, errors are returned where I can handle them, and tracing is simple. The costs are that both sides must be up at once, availability multiplies down a chain, and latency adds up. So I run independent calls in parallel, reuse pooled connections, and wrap every call with timeout, retry, and circuit breaker. Anything nobody is waiting on moves to a queue or an event."

Likely follow-ups:

  1. "Your endpoint calls five services and it is slow. Fix it without going async." Run independent calls in parallel, which changes total latency from the sum of all calls to the duration of the slowest one. Cache answers that change infrequently, verify that every call is necessary, and confirm that connections are reused.
  2. "When do you switch a call to async?" Switch when no person or service needs the answer to continue, or when the work takes longer than a connection should remain open. The change improves resilience but also introduces pending states, duplicates, and ordering decisions. It is a trade-off rather than an automatic upgrade.

A mistake that fails candidates: making a user-facing path asynchronous, such as placing a search on Kafka. Another mistake is drawing six synchronous calls without any failure protection. Both choices show an incomplete understanding of what synchrony costs and when its immediate answer is valuable.

7. Check Yourself

Q1 (recall). Which two questions decide sync versus async? And what three costs does every synchronous call add to a chain?

Q2 (trade-off). A checkout page makes five sequential 80 ms calls to services that are each 99.9% available. Calculate its latency and availability. Then improve both without making anything asynchronous.

Q3 (scenario). A teammate proposes making payment authorization asynchronous "for resilience." Checkout would publish a payment.requested event, and a worker would authorize it later. Assess the idea.

<details> <summary>Answers</summary>

A1. Ask whether the caller's next step depends on the answer and whether a person or machine is actively waiting. Each call creates temporal coupling because both sides must be available together. Availability multiplies across the chain, and latency adds when calls run sequentially.

A fourth cost is that every waiting caller occupies a thread. Timeout, retry, and circuit breaker protection are therefore required at scale.

A2. Latency: 5 x 80 ms = 400 ms. Availability: 0.999 multiplied five times = about 99.5%. That is about 44 hours of failed checkouts per year.

Three improvements preserve synchronous communication. Run independent calls in parallel, reducing latency to roughly the slowest call at 80-120 ms. Cache stable answers such as pricing rules, and remove calls whose results are unnecessary for rendering the page.

For better availability, identify which calls can fail without failing the entire page. Those areas can display less information instead of returning an error. The graceful degradation lesson develops this approach into a complete method.

A3. The proposal conflicts with the decision rule in this module. Checkout depends on the authorization result, and the user is waiting, so asynchronous processing does not eliminate the need for an answer.

Instead, it creates a pending state that the product team must define. The interface needs a clear state while payment.requested is processed, and duplicate delivery can cause repeated authorization attempts.

Protect the synchronous path directly. Add a timeout, then add retries with an idempotency key, which is a unique identifier that lets the service recognize a repeated request and prevent a double charge.

Also add a circuit breaker and define behavior for a genuine outage: save the cart, then email the customer after payment completes. Asynchronous delivery fits the receipt email because checkout does not depend on it.

</details>
  • Timeout, Retry, Circuit Breaker: the three protections. Request-response at scale is unsafe without all three.
  • Message Queue: the first alternative, for work nobody is waiting on.
  • Load Balancing: how one logical callee becomes many physical servers under this pattern.
  • API Gateway: where external request-response traffic is authenticated and rate-limited.

9. TL;DR

ProblemEvery arrow between services needs a default, and both mistakes are common: going async where someone is waiting, and adding synchronous calls in sequence until latency and fragility compound.
MechanismThe caller waits for the answer: a result or an error, now. Pool and reuse connections, run independent calls in parallel, and wrap every call with timeout, retry, and circuit breaker.
CostsBoth sides must be up at the same moment, availability multiplies per call, latency adds when sequential, and every waiting caller holds a thread.
Skip it whenNobody is waiting, the work takes too long for a held connection, many services care about the same event, or the chain has grown too deep.
30-second answerThe right default whenever the next step depends on the answer: a synchronous, traced, protected call, with independent calls in parallel, and everything nobody waits on moved to queues and events.
Flashcards Review

What is the request-response pattern?

1 / 18
General
Test Your Knowledge
Check your understanding and reinforce the key concepts covered in this section with a short, targeted assessment.
9 Questions
~14 mins
Your progress is saved automatically

Reading Progress

0%


Vote for new content

On This Page

  1. The Pattern
  1. What It Gives You
  1. What It Costs
  1. One Question Per Arrow
  1. When Not to Use It
  1. In the Interview
  1. Check Yourself
  1. Related Patterns
  1. TL;DR