Mastering Nginx: Production‑Ready SSE & WebSocket Proxy Configuration
Learn how to configure Nginx for reliable server‑sent events and WebSocket traffic in production, covering protocol basics, full‑stack Nginx templates, HTTPS/WSS support, Kubernetes Ingress settings, troubleshooting tips, and ready‑to‑use Node.js examples for both SSE and WebSocket.
1. SSE vs WebSocket – When to Use Which
SSE is unidirectional, uses HTTP/1.1, benefits from native browser reconnection, and streams plain text, making it ideal for AI streaming, notifications, and market data. WebSocket is bidirectional, follows its own protocol, requires heartbeat handling, supports text or binary, and suits real‑time chat, command streams, collaboration, and games.
2. Production‑Ready Nginx Configuration
The following global http block sets essential buffers, gzip (disabled for SSE), proxy defaults, and defines separate upstream groups for API, SSE, and WebSocket services.
http {
## WebSocket Upgrade mapping
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
## Gzip (disable for SSE)
gzip on;
gzip_proxied any;
gzip_types text/plain text/css application/json application/javascript application/xml;
gzip_min_length 1024;
gzip_comp_level 4;
## Proxy defaults
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 60s;
proxy_read_timeout 86400s; # long timeout for SSE/WS
proxy_send_timeout 86400s;
send_timeout 86400s;
client_body_buffer_size 10M;
client_max_body_size 50M;
## Upstreams
upstream app_api { server 127.0.0.1:9000; server 127.0.0.1:9001; }
upstream app_sse { server 127.0.0.1:9100; }
upstream app_ws { server 127.0.0.1:9200; }
}2.2 HTTP → HTTPS and Service Blocks
# HTTP → HTTPS redirect
server {
listen 80;
server_name your_domain.com;
return 301 https://$host$request_uri;
}
# HTTPS site with WS support
server {
listen 443 ssl http2;
server_name your_domain.com;
ssl_certificate /etc/nginx/cert/fullchain.pem;
ssl_certificate_key /etc/nginx/cert/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
# API
location /api/ { proxy_pass http://app_api; }
# SSE
location ^~ /sse/ {
proxy_pass http://app_sse;
proxy_buffering off;
proxy_cache off;
add_header X-Accel-Buffering no;
add_header Cache-Control no-store;
gzip off; # must disable compression for SSE
chunked_transfer_encoding on;
proxy_read_timeout 86400s;
proxy_send_timeout 86400s;
}
# WebSocket
location ^~ /ws/ {
proxy_pass http://app_ws;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_read_timeout 7d;
proxy_send_timeout 7d;
proxy_set_header X-Real-IP $remote_addr;
}
}This setup provides automatic HTTP→HTTPS redirection, WSS support, distinct upstreams for API, SSE, and WS, disables buffering and gzip for SSE, and correctly processes the WebSocket upgrade.
3. Kubernetes Ingress Settings
annotations:
nginx.ingress.kubernetes.io/proxy-read-timeout: "86400"
nginx.ingress.kubernetes.io/proxy-send-timeout: "86400"
nginx.ingress.kubernetes.io/proxy-buffering: "off"
nginx.ingress.kubernetes.io/enable-websocket: "true"
nginx.ingress.kubernetes.io/rewrite-target: /$1For WebSocket services, enable sessionAffinity: ClientIP to avoid routing errors across multiple nodes.
4. Server‑Side Example Code
4.1 SSE with Node.js
app.get('/sse/chat', (req, res) => {
res.set({
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive'
});
const timer = setInterval(() => {
res.write(`data: ${Date.now()}
`);
}, 1000);
req.on('close', () => clearInterval(timer));
});4.2 WebSocket with Node.js
const wsServer = new WebSocket.Server({ port: 9200 });
wsServer.on('connection', ws => {
ws.send("connected");
ws.on('message', msg => {
ws.send(`echo: ${msg}`);
});
});5. Common Production Issues and Fixes
SSE latency or stalling : Ensure proxy_buffering off and X-Accel-Buffering: no are set.
WebSocket disconnects : Add both Upgrade and Connection headers in the proxy.
WS fails over HTTPS : Use wss:// and valid TLS certificates.
Unstable WS in Kubernetes : Enable sticky sessions via sessionAffinity: ClientIP.
SSE breaks behind CDN : Disable CDN caching or bypass the CDN for SSE paths.
6. Diagnosis Commands
SSE test: curl -N https://your_domain/sse/test WebSocket test: wscat -c wss://your_domain/ws/chat Capture upgrade traffic:
tcpdump -i eth0 port 443 -w ws.pcap7. Ideal Architecture Diagram
Conclusion
The guide delivers a complete, production‑grade solution for proxying SSE and WebSocket with Nginx, including HTTP/HTTPS support, upstream separation, gzip/buffer tuning, Kubernetes Ingress configuration, troubleshooting checklist, and ready‑to‑run Node.js examples.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Ray's Galactic Tech
Practice together, never alone. We cover programming languages, development tools, learning methods, and pitfall notes. We simplify complex topics, guiding you from beginner to advanced. Weekly practical content—let's grow together!
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
