Node behind IIS or Nginx: WebSocket, SSE and proxy timeouts
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
The short answer
Section titled “The short answer”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.
IIS ARR
Section titled “IIS ARR”- 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.
Express/Node trust proxy
Section titled “Express/Node trust proxy”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-*.
Keep-alive and timeouts
Section titled “Keep-alive and timeouts”- Node server
keepAliveTimeoutshould be higher than the proxy’s idle timeout, or the proxy may reuse a socket the app just closed. - Proxy
proxy_read_timeoutshould exceed the longest response. - For SSE/WebSocket, a long read timeout is expected; for normal APIs, keep it short.
Verify
Section titled “Verify”curl.exe -I https://app.example/curl.exe -N https://app.example/eventsGet-Content C:\logs\api-a\out.log -Tail 50Check the app sees the public host/proto, SSE arrives incrementally, and WebSocket upgrades return 101.
Lab boundary
Section titled “Lab boundary”E1. The lab ran Nginx on 8081 but did not proxy a Node app; the configuration is the verification plan for Server 2025.