1.Connect, read and request deadlines are three different timeouts
A single "timeout" setting is not enough for a network call — three distinct deadlines cover three distinct failure modes. A connect timeout bounds how long to wait for the TCP handshake/connection to be established at all. A read timeout bounds how long to wait for data once the connection is open (a server that accepted the connection but never responds). A request (or total) timeout bounds the entire call end to end, including retries or streaming reads that could otherwise continue indefinitely one chunk at a time. Setting only one of these leaves the other failure modes completely unbounded.
Key features
- Connect timeout: bounds TCP handshake / connection establishment — protects against a dependency that is unreachable, not just slow to respond
- Read timeout (also called socket timeout): bounds the wait for data once connected — protects against a dependency that accepted the connection but is hung or silently stalled
- Request timeout (total/overall timeout): bounds the entire operation end to end, including any streaming or chunked reads — protects against a dependency that keeps sending small amounts of data forever without actually finishing
- A read timeout alone does not bound a chunked/streaming response that keeps arriving one byte at a time just under the read-timeout threshold — this is exactly what a request timeout catches and a read timeout cannot
- Most HTTP client libraries (e.g. Python requests, Go net/http, Java HttpClient) expose these as separate configurable values precisely because a single combined timeout cannot express all three failure modes correctly
The three deadlines and what each one alone catches
- Connect timeout — time to establish the connection
- Read timeout — time between chunks
- Request timeout — bounds the entire call
Command
import requests
requests.get(
"https://payments.internal/charge",
timeout=(3, 10), # (connect_timeout, read_timeout) in seconds
)A connect timeout bounds reaching the dependency at all; a read timeout bounds the wait between chunks once connected; a request timeout bounds the entire call. Setting only one leaves the other two failure modes completely unbounded — a chunked response trickling data just under the read timeout can hang forever without a request timeout to catch it.