SSE with Nginx — Complete Guide to Production Deployment
In this tutorial, you will learn about SSE with Nginx. We cover key concepts, practical examples, and best practices to help you master this topic.
SSE with nginx requires disabling buffering, enabling HTTP/2, and configuring proxy settings to ensure the event stream reaches clients without delay or truncation in production deployments.
What You'll Learn
- Essential nginx configuration for SSE proxying
- Disabling buffering and Caching for streaming
- Load Balancing SSE connections across backend servers
Why It Matters
Nginx buffers responses by default, which breaks SSE. Without proper configuration, nginx delays or batches event stream data, making real-time updates arrive in bursts instead of continuously.
Real-World Use
Doda Browser's notification service runs behind an nginx reverse proxy. The nginx config disables proxy buffering for /events endpoints and enables HTTP/2 so hundreds of simultaneous SSE connections are handled efficiently.
flowchart LR
C["Client"] --> N["nginx Proxy"]
N --> B1["Backend 1"]
N --> B2["Backend 2"]
N --> B3["Backend 3"]
N -->|"No Buffering"| C
style N fill:#dbeafe,stroke:#2563eb
Code Examples
# Basic nginx SSE configuration
server {
listen 443 ssl http2;
serverName api.example.com;
location /events {
proxy_pass http://backend:3000;
proxy_http_version 1.1;
proxy_set_header Connection '';
proxy_buffering off;
proxy_cache off;
proxy_read_timeout 24h;
proxy_send_timeout 24h;
chunked_transfer_encoding on;
}
}
Expected output: Nginx proxies SSE connections without buffering, streaming events to clients in real time.
# Advanced SSE with load balancing
upstream sse_backends {
least_connections;
server backend1:3000;
server backend2:3000;
server backend3:3000;
}
server {
listen 443 ssl http2;
location /events {
proxy_pass http://sse_backends;
proxy_http_version 1.1;
proxy_set_header Connection '';
proxy_buffering off;
proxy_cache off;
proxy_read_timeout 24h;
proxy_set_header X-Real-IP $remote_addr;
# Sticky sessions for stateful backends
sticky learn
create=$upstream_cookie_ssebackend
lookup=$cookie_ssebackend
zone=sse_sessions:10m;
}
}
Expected output: Load-balanced SSE with sticky sessions ensures clients reconnect to the same backend.
# nginx configuration validation and reload
sudo nginx -t
sudo systemctl reload nginx
# Check SSE connections
ss -tlnp | grep 443
tail -f /var/log/nginx/access.log | grep /events
Expected output: Configuration validated; SSE connections visible in system socket statistics.
Common Mistakes
1. Not Disabling Proxy Buffering
Nginx buffers responses by default, causing SSE data to arrive in bursts instead of continuously as events are sent.
2. Setting Timeout Too Low
The default proxy_read_timeout (60s) closes idle SSE connections. Set it to 24h or longer for persistent connections.
3. Using HTTP/1.1 Without Connection Header
Without proxy_set_header Connection '', nginx may use HTTP/1.0 to the backend, which does not support streaming.
4. Forgetting Sticky Sessions for Stateful Backends
If a client reconnects to a different backend that does not have its session state, the stream breaks.
5. Not Monitoring Connection Count
SSE connections are long-lived. Without monitoring, a slow connection leak can exhaust nginx worker connections.
Practice Questions
- Why does nginx break SSE by default?
- What nginx directive disables response buffering?
- Why should proxy_read_timeout be increased for SSE?
- What is sticky sessions and why is it important for SSE?
- How do you monitor nginx SSE connection counts?
Answers:
- Nginx buffers responses by default to improve performance for regular HTTP, but buffering breaks streaming.
- proxy_buffering off; disables response buffering for streaming endpoints.
- SSE connections are long-lived with idle periods; the default 60s timeout closes them prematurely.
- Sticky sessions route clients consistently to the same backend, preserving in-memory stream state.
- Use ss, netstat, or nginx stub_status module to monitor active connection counts.
Challenge: Set up a three-node SSE backend behind an nginx reverse proxy with HTTP/2, disabled buffering, 24h timeout, and sticky sessions. Test with 100 simultaneous connections.
FAQ
Mini Project
Deploy an SSE application behind nginx with the following configuration: HTTP/2 enabled, proxy buffering disabled, 24-hour timeout, sticky sessions, and least_connections load balancing across three backend instances. Test with a load generator.
What's Next
Learn about SSE with HTTP/2 for further performance improvements, or explore SSE load balancing strategies for scaling to thousands of connections.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro