From 98d02604aef3e548e6d07f285124edfa4212e080 Mon Sep 17 00:00:00 2001 From: Saadi Myftija Date: Fri, 22 May 2026 16:55:01 +0200 Subject: [PATCH] feat(webapp): make HTTP keep-alive timeout configurable Expose the Express server's `keepAliveTimeout` as `HTTP_KEEPALIVE_TIMEOUT_MS` so it can be tuned alongside the upstream load balancer's idle timeout without a redeploy. Default stays at 65s. --- .server-changes/configurable-http-keepalive-timeout.md | 6 ++++++ apps/webapp/server.ts | 6 +++++- 2 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 .server-changes/configurable-http-keepalive-timeout.md diff --git a/.server-changes/configurable-http-keepalive-timeout.md b/.server-changes/configurable-http-keepalive-timeout.md new file mode 100644 index 00000000000..982ace7fdc6 --- /dev/null +++ b/.server-changes/configurable-http-keepalive-timeout.md @@ -0,0 +1,6 @@ +--- +area: webapp +type: improvement +--- + +Make the Express server's `keepAliveTimeout` configurable via `HTTP_KEEPALIVE_TIMEOUT_MS` (defaults to the previous hardcoded 65000 ms). diff --git a/apps/webapp/server.ts b/apps/webapp/server.ts index e266c6985c8..8fd6d7438de 100644 --- a/apps/webapp/server.ts +++ b/apps/webapp/server.ts @@ -19,6 +19,10 @@ const ENABLE_CLUSTER = process.env.ENABLE_CLUSTER === "1"; const cpuCount = os.availableParallelism(); const WORKERS = Number.parseInt(process.env.WEB_CONCURRENCY || process.env.CLUSTER_WORKERS || "", 10) || cpuCount; +// Must be greater than the upstream load balancer's idle timeout to avoid the +// LB pipelining a request onto a connection Node has already closed (→ 502). +const HTTP_KEEPALIVE_TIMEOUT_MS = + Number.parseInt(process.env.HTTP_KEEPALIVE_TIMEOUT_MS || "", 10) || 65 * 1000; function forkWorkers() { for (let i = 0; i < WORKERS; i++) { @@ -200,7 +204,7 @@ if (ENABLE_CLUSTER && cluster.isPrimary) { } }); - server.keepAliveTimeout = 65 * 1000; + server.keepAliveTimeout = HTTP_KEEPALIVE_TIMEOUT_MS; // Mitigate against https://github.com/triggerdotdev/trigger.dev/security/dependabot/128 // by not allowing 2000+ headers to be sent and causing a DoS // headers will instead be limited by the maxHeaderSize