β‘ Real-time - WebSockets vs. SSE
Real-time communication is a βStatefulβ problem in a βStatelessβ world. A Programmer prioritizes Server-Sent Events (SSE) for unidirectional updates due to its simplicity and only reaches for WebSockets when full-duplex (two-way) communication is strictly necessary.
π‘ Server-Sent Events (SSE)
Section titled βπ‘ Server-Sent Events (SSE)βSSE is a standard allowing servers to push data to web pages over HTTP. It is essentially a long-lived HTTP connection where the server keeps the response open.
- Unidirectional: Server β Client only.
- Protocol: Standard HTTP. Works over HTTP/1.1 and is even better over HTTP/2.
- Automatic Reconnection: Browsers handle reconnections natively.
- Ease of Use: Simple to implement on both backend (text/event-stream) and frontend (
EventSourceAPI).
Use Cases:
Section titled βUse Cases:β- Live score updates.
- Social media news feeds.
- System notifications or status progress bars.
π WebSockets (WS/WSS)
Section titled βπ WebSockets (WS/WSS)βA distinct protocol (built over TCP) that provides a persistent, full-duplex connection between client and server.
- Bi-directional: Server β Client. Both can send data at any time.
- Stateful: The server must keep an open socket for every connected user.
- Binary Support: Can send both text and binary data efficiently.
ποΈ Scaling Real-time Architectures
Section titled βποΈ Scaling Real-time ArchitecturesβWhen you move from one server to a cluster, real-time connections become difficult because Client A might be connected to Server 1, but the event they need is triggered on Server 2.
1. The Pub/Sub Pattern
Section titled β1. The Pub/Sub PatternβTo synchronize messages across multiple backend instances, you need a message broker (usually Redis).
- Process: When an event occurs on Server 2, it publishes a message to a Redis channel. Server 1 (and all other instances) is subscribed to that channel and pushes the message to its connected clients.
2. Sticky Sessions
Section titled β2. Sticky SessionsβSince WebSockets start with an HTTP handshake, your Load Balancer must support Session Affinity (Sticky Sessions). This ensures the handshake and the subsequent protocol upgrade happen on the same physical server.
3. Connection Limits
Section titled β3. Connection LimitsβThe OS has a limit on βOpen File Descriptors.β Each WebSocket counts as one.
- Tip: You may need to tune the
ulimiton your Linux servers or use a specialized proxy like HAProxy or Nginx to handle tens of thousands of concurrent connections.
βοΈ Comparative Decision Matrix
Section titled ββοΈ Comparative Decision Matrixβ| Feature | SSE | WebSockets |
|---|---|---|
| Direction | One-way (Server to Client) | Two-way (Bi-directional) |
| Protocol | Standard HTTP | WS Protocol (Upgrade) |
| Reconnection | Native / Automatic | Manual implementation required |
| Firewall Friendly | Yes (standard port 80/443) | Can be blocked by strict proxies |
| Max Connections | Limited by browser (6 per domain) | Limited by server resources |
π οΈ Implementation Patterns
Section titled βπ οΈ Implementation PatternsβHeartbeats (Ping/Pong)
Section titled βHeartbeats (Ping/Pong)βNetwork intermediaries (firewalls, load balancers) often kill βidleβ connections.
- Solution: Implement a βHeartbeatβ where the server or client sends a tiny packet every 30 seconds to prove the connection is still alive.
Authentication
Section titled βAuthenticationβYou cannot send custom headers with the standard browser WebSocket API.
- Workaround: Pass the JWT/Token as a Query Parameter (less secure, appears in logs) or perform a βTicket-basedβ authentication:
- Client requests a short-lived βticketβ via a REST POST.
- Server returns a UUID.
- Client connects to WS via
ws://api.com?ticket=UUID.
π‘ Note: βReal-timeβ doesnβt always mean βWebSockets.β If your data updates every 10 seconds, Long Polling or even Short Polling with aggressive caching might be 10x cheaper to run and 100x easier to maintain than a WebSocket cluster.