Timeout Pattern

How to protect your services from indefinite waits by setting time limits on calls to external dependencies.

What problem it solves

When a service calls another service or external resource, the call can end up waiting indefinitely if the receiver is slow or unresponsive. Without a configured timeout, the calling service keeps the connection open, ties up a thread from the pool, and eventually exhausts all of its resources.

Without Timeout:
  Service A ──► Service B (slow, unresponsive)
                 ⏳ Waiting... 10s
                 ⏳ Waiting... 30s
                 ⏳ Waiting... 60s
                 ⏳ Waiting... 120s
                 
  Service A's thread blocked indefinitely
  More requests arrive β†’ more threads blocked
  Thread pool exhausted β†’ Service A stops responding

This is one of the most common and dangerous problems in distributed systems. A slow service can be worse than a down service, because a down service fails fast, while a slow one consumes resources over an extended period.

How it works

The Timeout pattern sets a maximum time limit for each call to a dependency. If the response does not arrive within the configured time, the call is canceled and an error is returned or a fallback is executed.

With Timeout (5 seconds):
  Service A ──► Service B (slow)
                 ⏳ Waiting... 1s
                 ⏳ Waiting... 3s
                 ⏳ Waiting... 5s
                 ⏠ TIMEOUT β†’ Error or fallback
  
  Thread released after 5 seconds
  Service A can handle other requests

Types of timeout

TypeDescriptionExample
Connection timeoutMaximum time to establish the TCP connection2-5 seconds
Read/Response timeoutMaximum time to receive the complete response5-30 seconds
Request timeoutTotal time of the operation (connection + read)10-60 seconds
Idle timeoutMaximum idle time on an open connection30-120 seconds

How to choose the timeout value

There is no universal value. The timeout should be based on real data:

Step 1: Measure the service's normal latency
  P50 (median): 100ms
  P95: 500ms
  P99: 2s

Step 2: Set the timeout with a margin
  Timeout = P99 Γ— 2 = 4 seconds
  
  This lets 99% of normal calls complete,
  but cuts off those that take abnormally long.
CriterionSuggested timeoutReasoning
Fast internal API1-3 secondsExpected latency < 200ms
Internal API with DB5-10 secondsComplex queries can take time
External (third-party) API10-30 secondsLess control over latency
Batch operation60-300 secondsHeavy processing expected
Health check2-5 secondsMust respond fast or it’s unhealthy

Chained timeouts

In a chain of calls, timeouts should be decreasing to prevent an intermediate service from waiting longer than the service that called it:

Client (timeout: 30s)
  └──► API Gateway (timeout: 25s)
         └──► Service A (timeout: 10s)
                └──► Service B (timeout: 5s)

If Service B takes 6s:
  Service B: times out at 5s β†’ error
  Service A: receives error, can fall back
  API Gateway: receives response from A (with fallback)
  Client: receives response within its 30s

If the timeouts are not decreasing, the client may have already abandoned the request by the time the service finally responds, wasting resources.

Strategies on timeout

StrategyDescriptionWhen to use
Immediate errorReturn HTTP 504 Gateway TimeoutWhen there is no alternative
FallbackReturn cached or default dataWhen alternative data is available
RetryRetry the operationWhen the failure may be transient
DegradationOffer reduced functionalityWhen partial data is sufficient

Advantages

  • Resource release: Threads are not blocked indefinitely
  • Fail fast: The user receives a response (even an error) in a predictable time
  • Cascade prevention: A slow service does not drag down those that depend on it
  • Simple implementation: Most HTTP clients and frameworks support timeouts natively
  • Predictability: The system’s maximum response time is known and bounded
  • Foundation for other patterns: Timeouts feed the Circuit Breaker’s metrics and the Retry’s reattempts

Trade-offs / Disadvantages

  • False positives: An overly aggressive timeout can cut off legitimate operations that take longer than usual
  • Orphaned operations: The downstream service may complete the operation after the timeout, causing inconsistencies
  • Delicate configuration: Incorrect values cause more problems than solutions
  • Doesn’t fix the root cause: The timeout protects the caller, but the slow service still needs to be fixed
  • Complexity in chains: Coordinating timeouts across service chains requires careful design

When to use

  • Every call to an external service or network dependency (this is a mandatory practice)
  • Database queries that can block due to locks or slow queries
  • Calls to third-party APIs with variable latency
  • Any I/O operation that can block indefinitely
  • As a complement to the Circuit Breaker (the timeout defines when a call is considered failed)

When to avoid

  • Local in-memory operations where a timeout makes no sense
  • Long-running batch processes where the timeout should be very high or handled differently (progress tracking)
  • Continuous data streams where the connection must stay open (use heartbeats instead)

Common technologies and implementations

CategoryOptions
HTTP ClientsAxios (Node.js), HttpClient (.NET), OkHttp (Java), requests (Python)
FrameworksSpring Boot (timeout configuration), ASP.NET Core, Express.js
DatabasesConnection pool timeouts, query timeouts, statement timeouts
Service MeshIstio, Linkerd, Envoy (infrastructure-level timeouts)
CloudAWS ALB/NLB timeouts, Azure Application Gateway, Cloud Load Balancing

Relationship with other patterns

Request
   β”‚
   β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Timeout  β”‚ ← Defines how long to wait
β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜
     β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Retry   β”‚ ← Retries on timeout
β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜
     β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Circuit  β”‚ ← Opens on many timeouts
β”‚ Breaker  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
  • Retry: When a timeout occurs, Retry can reattempt the operation
  • Circuit Breaker: Timeouts count as failures; many timeouts open the circuit
  • Bulkhead: Isolates resources so that one service’s timeouts don’t affect others
  • Fallback: The response strategy when a timeout occurs

Next steps

Timeout is the foundation of every resilience strategy. To handle reattempts after a timeout, explore the Retry pattern. To understand how timeouts feed the Circuit Breaker, check out the Circuit Breaker article.