Back to Initiative Library
Config & Standards Low complexity

Node.js HTTP Server Timeout Configuration

✦ Sample Prompt
Set explicit HTTP server timeouts on every Node.js service so slowloris attacks
and load-balancer keep-alive races stop producing 502s.

Target values (assume an ALB with 60s idle timeout; adjust before running):
- `server.keepAliveTimeout = 65_000`
- `server.headersTimeout = 66_000`   // must be greater than keepAliveTimeout
- `server.requestTimeout = 30_000`

For each repository:
1. Find the HTTP server creation site. Common patterns:
   - Express: `const server = http.createServer(app)` or `app.listen(...)` (which
     returns the server). Capture the returned server reference if needed.
   - Fastify: `const app = Fastify(...)`; set timeouts on `app.server`
   - Koa: `const server = app.listen(...)`; same pattern
   - Raw: `const server = http.createServer(...)`
2. Insert the three `server.<timeout> = ...` assignments immediately before
   `server.listen(...)`.
3. Ensure `headersTimeout` is greater than `keepAliveTimeout` (the bug is the
   opposite order).
4. Skip files that already set all three timeouts explicitly.
5. If the entrypoint uses a custom server wrapper, modify the wrapper instead of
   the entrypoint.

The Problem

Node.js HTTP server defaults are dangerous in production. Without explicit timeouts, a slow client can hold a socket open forever (slowloris), and the keep-alive timeout interacts badly with most load balancers (the LB holds the connection two milliseconds longer than Node does, producing 502s under load).

The fix is three lines per server, but every service has its own entrypoint and its own framework wrapper. Express, Fastify, Koa, and raw `http.createServer` all need slightly different patches.

What Tidra Does

  1. Identifies the HTTP server creation site in each service (Express, Fastify, Koa, raw http)
  2. Sets server.headersTimeout, server.requestTimeout, and server.keepAliveTimeout to the values you specify
  3. Ensures keepAliveTimeout is greater than your load balancer’s idle timeout
  4. Skips services that already configure these explicitly
  5. Opens one PR per repo with a link to the SRE runbook explaining the values

Before & After

diff
src/server.ts
@@ -8,5 +8,9 @@
const app = express();
const server = http.createServer(app);
+ server.keepAliveTimeout = 65_000;
+ server.headersTimeout = 66_000;
+ server.requestTimeout = 30_000;
+
server.listen(port, () => console.log(`listening on ${port}`));

Customization Tips

  • Values: Defaults assume an ALB with 60s idle timeout. If your LB differs, adjust the prompt before running.
  • Framework variants: Fastify exposes the same properties via app.server. Koa uses app.listen().on(...). Both are handled.
  • TLS servers: TLS-terminating Node servers need the same three timeouts plus sessionTimeout. Include in the prompt if relevant.

Ready to run this across your repos?

Connect your Git provider and Tidra opens pull requests in every repo that needs them.