An HTTP timeout is the maximum time a client will wait for a server to respond before giving up and treating the request as failed. Timeouts exist because waiting forever is never an option — if a server is down or overloaded, your application needs to move on.
How long the client waits to establish a TCP connection with the server. If the server is unreachable (wrong IP, firewall blocking, server down), the connection timeout fires. Typical values: 5 to 10 seconds.
How long the client waits for the server to send back data after the connection is established. The connection succeeded, but the server is taking too long to process the request and return a response. Typical values: 15 to 60 seconds.
How long the client waits while sending the request body to the server. Relevant for large uploads or slow connections. Less commonly configured than connection and read timeouts.
A cap on the entire request lifecycle — from opening the connection to receiving the last byte of the response. Useful as a safety net when you want a hard upper bound regardless of which phase is slow.
There's no universal answer, but here are guidelines:
| Scenario | Suggested timeout |
|---|---|
| Fast API call (user lookup, status check) | 5 – 10 seconds |
| Standard API call (create record, send email) | 15 – 30 seconds |
| Heavy processing (report generation, data export) | 60 – 120 seconds |
| Webhook delivery | 10 – 30 seconds |
The key principle: set the timeout higher than the endpoint's typical response time, but low enough to fail fast when something is genuinely broken. If your endpoint normally responds in 200ms, a 30-second timeout is generous enough for slow outliers while still catching real failures.
From the client's perspective, a timeout looks like a failure — the request didn't complete. But from the server's perspective, the request may have succeeded. The server might have processed the payment, sent the email, or updated the database — it just didn't respond in time.
This is why idempotency is critical. When you retry a timed-out job, you might be retrying something that already succeeded. If the job isn't idempotent, the retry causes duplicate side effects.
After a timeout, the job returns to the queue for retry — typically with exponential backoff. If the endpoint is temporarily slow, the backoff gives it time to recover. If it's permanently broken, the job eventually lands in the dead letter queue.
| Service | Default timeout |
|---|---|
| AWS Lambda (via API Gateway) | 29 seconds |
| Cloudflare Workers | 30 seconds (free), configurable (paid) |
| Vercel Serverless Functions | 10 – 300 seconds (plan-dependent) |
| Stripe webhook delivery | 20 seconds |
| GitHub webhook delivery | 10 seconds |
An HTTP timeout is the maximum time a client will wait for a server to respond. If the server doesn't respond within that window, the client abandons the request and treats it as a failure.
A connection timeout fires when the client can't establish a connection at all (server unreachable). A read timeout fires when the connection is established but the server takes too long to send back a response (server is slow or overloaded). They're separate failure modes with different causes.
Measure your endpoint's actual response times under normal load. Set the timeout to 3–5x the P95 response time. This accommodates outliers while still failing fast on genuine problems. For background jobs, err on the generous side since users aren't waiting.
Timeout failures should trigger backoff retries. Jobs that time out may have partially executed, so idempotency protects against duplicate side effects. Timeouts and rate limits are the top two causes of background job failures.
Recuro handles cron scheduling, retries, alerts, and execution logs -- so you can focus on building your product.
No credit card required