Server Sent Events In a Kubernetes Cluster
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.
Introduction
Server-Sent Events (SSE) enable a server to push real-time updates to clients over a single long-lived HTTP connection. Running SSE in Kubernetes introduces challenges around connection persistence, load balancer timeouts, pod scaling, and graceful shutdowns. Unlike WebSockets, SSE uses plain HTTP, which simplifies infrastructure but requires careful configuration of ingress controllers, timeouts, and buffering to prevent connections from being silently dropped.
How SSE Works
The client opens a single HTTP request, and the server sends events as they occur. The connection remains open indefinitely. If it drops, the browser's EventSource API automatically reconnects.
Basic SSE Server (Node.js)
Kubernetes Deployment
Ingress Configuration (NGINX)
The most critical piece — NGINX ingress must not timeout or buffer SSE connections:
Key annotations:
proxy-read-timeout: "3600"— keep connections open for 1 hour (default is 60s)proxy-buffering: "off"— send events immediately without bufferingproxy-cache: "off"— do not cache event streams
Session Affinity (Sticky Sessions)
SSE connections are stateful — a client should reconnect to the same pod if possible:
Without sticky sessions, a reconnecting client may hit a different pod that does not have its subscription state.
Graceful Shutdown
When a pod is terminated (scaling down, rolling update), active SSE connections must be closed cleanly:
Set terminationGracePeriodSeconds in the pod spec to give the shutdown handler enough time.
Scaling Considerations
With multiple pods, each pod only knows about its own connected clients. To broadcast events to all clients across pods, use a message broker:
Horizontal Pod Autoscaler
Scale based on connection count rather than CPU, since SSE connections are mostly idle but consume memory and file descriptors.
Common Pitfalls
- Default NGINX timeout kills connections: The default
proxy-read-timeoutis 60 seconds. SSE connections that go 60 seconds without an event are terminated. Set it to 3600 or higher, and send periodic heartbeat events (:heartbeat\n\n) to keep the connection alive. - Proxy buffering delays events: NGINX and cloud load balancers buffer responses by default. A buffered SSE event is not sent until the buffer fills, causing delayed or batched delivery. Set
proxy-buffering: offandX-Accel-Buffering: no. - Pod termination drops connections without notice: Without a graceful shutdown handler, Kubernetes kills the pod and clients see a network error. Send a close event before shutting down and set an adequate
terminationGracePeriodSeconds. - No cross-pod broadcasting: Each pod only pushes events to its own clients. Without Redis Pub/Sub or a similar message bus, events published on one pod are invisible to clients connected to other pods.
- File descriptor limits: Each SSE connection uses a file descriptor. The default
ulimitmay be too low for thousands of connections. Setulimit -n 65535in the container or usesecurityContext.rlimitsin the pod spec.
Summary
- SSE uses long-lived HTTP connections — configure ingress timeouts to 3600+ seconds
- Disable proxy buffering (
proxy-buffering: off) to deliver events immediately - Use session affinity (sticky sessions) so reconnecting clients hit the same pod
- Implement graceful shutdown to close SSE connections cleanly during pod termination
- Use Redis Pub/Sub or a message broker to broadcast events across multiple pods
- Scale based on connection count rather than CPU for SSE workloads
Related reading
- Service located in another namespace
- Service selection from only one pod of one statefulset
- services is forbidden User systemserviceaccounttickexternal-dns cannot list resource services in API group at the cluster scope
- set annotation/label with slash / in mutating-webhook of opa-gatekeeper
- Serverless framework deployment error You're not authorized to access this resource
- Serverless Framework with AWS Lambda error Cannot find module
- Service discovery vs load balancing
- Service Meshes like Istio vs. Event-Driven architecture for Microservices

System Design Fundamentals
Build a strong foundation in designing scalable, reliable distributed systems.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.