Timeouts, Retries, and Exponential Backoff with Jitter
Bound every outbound call and retry transient failures without amplifying load on dependencies.
Why Bound Every Outbound Call
In a Node.js backend, every call that leaves your process (HTTP request, database query, message broker publish) is a place where you can hang forever. A slow dependency does not just delay one request, it pins an event-loop tick, holds a socket, and keeps a connection-pool slot busy.
- Unbounded latency cascades: one stuck downstream call multiplies into thousands of stuck inbound requests.
- Resource exhaustion: sockets, file descriptors, and pool connections leak while you wait.
- No SLA without a deadline: you cannot promise a p99 latency if a call has no upper bound.
The first rule of production resilience: never make an outbound call without a timeout. Retries and backoff build on top of that bound.
Timeouts with AbortSignal.timeout
Modern Node.js (18+) ships AbortSignal.timeout(ms), which produces a signal that aborts automatically after the deadline. The global fetch accepts a signal, so bounding an HTTP call is a one-liner.
- When the timeout fires, the promise rejects with an
AbortError(err.name === 'AbortError'). - The signal is fire-and-forget: no manual
clearTimeoutneeded. - Always distinguish a timeout abort from other network errors so you log and retry correctly.
async function fetchWithTimeout(url, ms) {
try {
const res = await fetch(url, { signal: AbortSignal.timeout(ms) });
if (!res.ok) throw new Error('HTTP ' + res.status);
return await res.json();
} catch (err) {
if (err.name === 'AbortError' || err.name === 'TimeoutError') {
throw new Error('Request timed out after ' + ms + 'ms');
}
throw err;
}
}
// Demo against a hung promise (no real network)
function hang(signal) {
return new Promise((_, reject) => {
signal.addEventListener('abort', () => reject(signal.reason));
});
}
(async () => {
try {
await hang(AbortSignal.timeout(50));
} catch (e) {
console.log('Aborted:', e.name);
}
})();All lessons in this course
- Timeouts, Retries, and Exponential Backoff with Jitter
- The Circuit Breaker Pattern and Bulkhead Isolation
- Graceful Shutdown and In-Flight Request Draining
- Health Checks, Readiness Probes, and Load Shedding