nextjs - 💡(How to fix) Fix Standalone server: expose headersTimeout (HEADERS_TIMEOUT env) symmetric to KEEP_ALIVE_TIMEOUT [1 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
vercel/next.js#93290Fetched 2026-04-28 06:23:27
View on GitHub
Comments
1
Participants
2
Timeline
4
Reactions
0
Timeline (top)
closed ×1commented ×1labeled ×1locked ×1

Fix Action

Fix / Workaround

The community workaround today is either:

  1. Drop the standalone output entirely and write a custom server.js that sets both timeouts — significant overhead and re-implements what start-server.js already does.
  2. Preload a --require shim that monkey-patches http.Server.prototype.listen to fix headersTimeout before bind.

Code Example

if (keepAliveTimeout) {
  server.keepAliveTimeout = keepAliveTimeout;
}
RAW_BUFFERClick to expand / collapse

Describe the feature you'd like to request

The standalone server reads KEEP_ALIVE_TIMEOUT from env and applies it to server.keepAliveTimeout (added in #46052). However, server.headersTimeout is never set, so it stays at Node's default (60s on Node ≥ 18).

This asymmetry creates a 502 footgun for any deployment that follows the documented pattern of raising keepAliveTimeout to beat an upstream proxy's idle timeout: as soon as keepAliveTimeout is set to a value ≥ Node's default headersTimeout (60s), the invariant headersTimeout > keepAliveTimeout is broken, and Node bug nodejs/node#27363 reappears (proxy reuses an idle connection, server tears it down mid-request, proxy returns 502). Node's own docs recommend headersTimeout be strictly greater than keepAliveTimeout.

The community workaround today is either:

  1. Drop the standalone output entirely and write a custom server.js that sets both timeouts — significant overhead and re-implements what start-server.js already does.
  2. Preload a --require shim that monkey-patches http.Server.prototype.listen to fix headersTimeout before bind.

Both feel hacky for a problem that affects every Next.js standalone deployment behind nginx-ingress, ALB, or any other proxy with a keepalive idle timeout > Node's default headersTimeout.

Proposed change

Add a HEADERS_TIMEOUT env var, parsed and applied alongside KEEP_ALIVE_TIMEOUT in server/lib/start-server.ts. Concretely, in the same block that currently does:

if (keepAliveTimeout) {
  server.keepAliveTimeout = keepAliveTimeout;
}

…also read process.env.HEADERS_TIMEOUT (or thread it through serverOptions), parse to int, and set server.headersTimeout if present and positive. Document in the env-vars reference that HEADERS_TIMEOUT should be set to a value strictly greater than KEEP_ALIVE_TIMEOUT (per Node docs) — or, ideally, default it to keepAliveTimeout + 1000 when only KEEP_ALIVE_TIMEOUT is set, so the safe behavior is the default.

Why it matters

  • Closed predecessor #28633 (2021) requested both timeouts; only keepAliveTimeout shipped (#46052)
  • The widely-cited Vercel discussion #28642 recommends raising keepAliveTimeout to beat the upstream proxy timeout, but does not mention headersTimeout — meaning anyone who follows that guidance and runs Node 18+ silently hits the second race
  • Today's standalone output is one env var away from being safe; the surface area is tiny

Verifications

  • I have searched the existing issues

extent analysis

TL;DR

Set HEADERS_TIMEOUT to a value strictly greater than KEEP_ALIVE_TIMEOUT to prevent the 502 footgun issue.

Guidance

  • Introduce a new environment variable HEADERS_TIMEOUT to control server.headersTimeout and ensure it's greater than KEEP_ALIVE_TIMEOUT.
  • Update server/lib/start-server.ts to parse and apply HEADERS_TIMEOUT alongside KEEP_ALIVE_TIMEOUT.
  • Consider defaulting HEADERS_TIMEOUT to KEEP_ALIVE_TIMEOUT + 1000 when only KEEP_ALIVE_TIMEOUT is set to ensure safe behavior by default.
  • Document the relationship between HEADERS_TIMEOUT and KEEP_ALIVE_TIMEOUT in the environment variables reference.

Example

if (keepAliveTimeout) {
  server.keepAliveTimeout = keepAliveTimeout;
}
const headersTimeout = parseInt(process.env.HEADERS_TIMEOUT, 10);
if (headersTimeout > 0) {
  server.headersTimeout = headersTimeout;
} else if (keepAliveTimeout) {
  // Default headersTimeout to keepAliveTimeout + 1000
  server.headersTimeout = keepAliveTimeout + 1000;
}

Notes

The proposed solution relies on introducing a new environment variable and updating the server configuration to apply it. This approach aims to prevent the 502 issue by ensuring headersTimeout is always greater than keepAliveTimeout.

Recommendation

Apply the workaround by introducing the HEADERS_TIMEOUT environment variable and updating the server configuration, as this provides a straightforward solution to the issue without requiring significant changes to the existing codebase.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

nextjs - 💡(How to fix) Fix Standalone server: expose headersTimeout (HEADERS_TIMEOUT env) symmetric to KEEP_ALIVE_TIMEOUT [1 comments, 2 participants]