patterntypescriptexpressMajor
Request Timeout Handling in Node.js APIs
Viewed 0 times
Node.js 14.11+
timeoutAbortControllerrequestTimeoutupstream timeout503408
node
Error Messages
Problem
Requests to slow upstream services hold connections open indefinitely, exhausting server resources. Clients get no feedback and eventually time out on their end.
Solution
Set explicit timeouts at the HTTP server level and on upstream fetch calls.
import http from 'node:http';
const server = http.createServer(app);
server.requestTimeout = 30_000; // 30s
server.headersTimeout = 60_000;
// Upstream fetch with AbortController
async function fetchWithTimeout(url: string, ms: number): Promise<Response> {
const controller = new AbortController();
const timer = setTimeout(() => controller.abort(), ms);
try {
return await fetch(url, { signal: controller.signal });
} catch (e) {
if (e instanceof Error && e.name === 'AbortError') {
throw new Error(`Upstream timeout after ${ms}ms`);
}
throw e;
} finally {
clearTimeout(timer);
}
}
// Per-route timeout middleware
function withTimeout(ms: number): RequestHandler {
return (req, res, next) => {
const timer = setTimeout(() => {
if (!res.headersSent) {
res.status(503).json({ error: 'Request timeout' });
}
}, ms);
res.on('finish', () => clearTimeout(timer));
next();
};
}Why
Without timeouts, slow upstream services cascade into server resource exhaustion. Each pending request holds an open socket and memory even though Node.js is non-blocking.
Gotchas
- server.requestTimeout was added in Node.js 14.11 — older versions need custom middleware.
- Always clear the AbortController timer in a finally block to prevent memory leaks.
- Gateway timeouts from Nginx or load balancers are separate — set both.
Revisions (0)
No revisions yet.