NetworkingWebSockets & Real-Time Communication

WebSockets enable full-duplex, persistent connections between client and server — enabling real-time features like chat, live feeds, and collaborative editing without the overhead of repeated HTTP requests.

The Problem with HTTP for Real-Time

HTTP is a request-response protocol. To get updates, the client must ask. For real-time apps (chat, live scores, collaborative docs), this creates a dilemma:

  • Short polling: Client asks every N seconds → Wastes bandwidth, high latency
  • Long polling: Client makes a request; server holds it open until data is available, then returns → Better, but awkward and scales poorly

WebSockets solve this properly.

WebSockets

WebSockets establish a single, persistent TCP connection that both the client and server can use to send messages at any time.

Handshake

Client → Server: HTTP Upgrade request
Server → Client: 101 Switching Protocols
[Connection is now a WebSocket — bidirectional, persistent]

Pros:

  • True bidirectional communication — server can push without a client request
  • Low overhead after handshake (no HTTP headers on each message)
  • Low latency — no connection setup per message

Cons:

  • Stateful — connections are pinned to a server (complicates horizontal scaling)
  • Requires special handling in proxies and load balancers
  • Not cacheable
  • More complex error handling (reconnection, heartbeats)

Best for: Chat, collaborative tools, live dashboards, multiplayer games, trading platforms

Server-Sent Events (SSE)

SSE is a simpler alternative for one-way server-to-client streaming over HTTP.

const source = new EventSource('/api/stream');
source.onmessage = (event) => console.log(event.data);

Pros:

  • Works over standard HTTP (no upgrade needed)
  • Native browser support, automatic reconnection
  • Works through HTTP/2 multiplexing

Cons:

  • One-directional (server → client only)
  • Limited to UTF-8 text

Best for: Live feeds, notifications, progress updates — where the client only needs to listen

Scaling WebSockets

This is the key challenge. Because WebSocket connections are persistent and stateful:

The Problem

User A and User B are connected to different servers. User A sends a message — it arrives at Server 1, but User B is on Server 2.

Solutions

Sticky Sessions: Route each user to the same server consistently (via load balancer IP hash). Simple but limits load balancing flexibility.

Pub/Sub Backplane: Servers publish messages to a shared channel (Redis Pub/Sub, Kafka). All servers subscribe and forward messages to their connected clients.

Server 1 (User A) → publish("room:chat", msg) → Redis
Redis → broadcast → Server 2 (User B) → User B receives msg

Dedicated WebSocket Service: Separate the WebSocket layer from business logic. Stateless WebSocket servers only handle connection management; business logic runs elsewhere.

Choosing the Right Approach

| Need | Solution | |---|---| | Server-to-client updates | SSE | | Bidirectional real-time | WebSockets | | Infrequent updates, simple setup | Long polling | | Push notifications (mobile) | APNS / FCM |

Interview Tips

  • Mention the scaling challenge (stateful connections) whenever you use WebSockets, and explain how you'd solve it (Redis pub/sub)
  • For most real-time features, know which direction data flows — many features only need server→client (use SSE)
  • Heartbeat/ping-pong is needed to detect broken connections — mention this for reliability
  • For massive scale (millions of connections), services like Socket.IO with Redis adapter, or managed services like AWS API Gateway WebSocket APIs or Pusher, are worth mentioning