Skip to content

Node behind IIS or Nginx: WebSocket, SSE and proxy timeouts

Verified 1 min read

Reverse-proxy Node with correct Host/X-Forwarded headers, WebSocket upgrades, SSE buffering and timeouts that do not cut long connections.

Tested onStandard / Datacenter · Build 26100.33650 · x64
E1
Build
26100.33650
Edition
Standard / Datacenter
Architecture
x64
Support
Documentation (E1)
Evidence
E1Official documentation
Verified
2026-10-29
Page type
Task

Node listens on 127.0.0.1:3000; IIS ARR or Nginx owns 443. The proxy must:

  • preserve Host;
  • send X-Forwarded-For/X-Forwarded-Proto;
  • allow WebSocket upgrade;
  • not buffer SSE;
  • use a read timeout longer than the longest legitimate connection.
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 60s;
}

WebSocket:

proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_read_timeout 3600s;

SSE:

proxy_buffering off;
proxy_cache off;
proxy_read_timeout 3600s;

Without proxy_buffering off, events may arrive in bursts or not until the connection closes.

  • Farm to 127.0.0.1:3000.
  • Preserve Host, forward XFF/XFP.
  • Enable WebSocket in the ARR/farm settings if the app uses it.
  • Set proxy timeout; do not disable it globally.
app.set('trust proxy', 1);

Set this only when the app is behind a trusted proxy. Then req.ip, req.protocol and secure cookies behave correctly. trust proxy when Node is directly exposed lets clients spoof X-Forwarded-*.

  • Node server keepAliveTimeout should be higher than the proxy’s idle timeout, or the proxy may reuse a socket the app just closed.
  • Proxy proxy_read_timeout should exceed the longest response.
  • For SSE/WebSocket, a long read timeout is expected; for normal APIs, keep it short.
Terminal window
curl.exe -I https://app.example/
curl.exe -N https://app.example/events
Get-Content C:\logs\api-a\out.log -Tail 50

Check the app sees the public host/proto, SSE arrives incrementally, and WebSocket upgrades return 101.

E1. The lab ran Nginx on 8081 but did not proxy a Node app; the configuration is the verification plan for Server 2025.

Sources