Interview frequency: …
Short answer
Always set a timeout, reuse a single client (connection pooling), check the status code explicitly, and distinguish transport errors (timeouts and dropped connections) from HTTP errors (4xx and 5xx).
Explanation
Some libraries have no default timeout (such as requests), so a request may hang forever. Creating a new client for every request defeats connection reuse and adds a handshake each time. A successful connection does not mean a successful request; use raise_for_status or check the status. Retry only on transient errors (such as 503 and 429 with Retry-After), and do not log authentication headers. For async code use httpx.AsyncClient or aiohttp.
Code example
import httpx
client = httpx.Client(base_url="https://api.example.com", timeout=httpx.Timeout(5.0, connect=2.0))
def get_order(order_id: int) -> dict:
try:
response = client.get(f"/orders/{order_id}")
response.raise_for_status()
except httpx.TimeoutException as err:
raise UpstreamTimeout() from err
except httpx.HTTPStatusError as err:
if err.response.status_code == 404:
raise OrderNotFound(order_id) from err
raise
return response.json()Common mistakes
- Calling requests.get without a timeout in production code.
- Creating a new client inside every request function.