Networking

Real-Time Communication

Real-time features, chat, notifications, live dashboards, collaborative editing, need the server to get data to clients as it happens. The main techniques are short polling, long polling, Server-Sent Events, WebSockets, and WebRTC, each with distinct cost and capability profiles.

Short and Long Polling

Short polling is the naive baseline: the client requests updates on a timer, GET /messages?since=... every 3 seconds. It works through every proxy and firewall on earth and needs zero special infrastructure, but the tradeoff is stark: average latency is half the polling interval, and almost all requests return empty. A million clients polling every 5 seconds is 200,000 requests per second of mostly nothing. It remains reasonable for slow-changing data, a dashboard refreshing every 30-60 seconds, or as a dead-simple fallback.

Long polling improves on this by parking the request: the server holds the connection open until data arrives or a timeout (commonly 30-60 seconds) fires, responds, and the client immediately re-requests. Latency drops to near-instant and empty responses mostly disappear, at the cost of the server holding one open request per client, which demands an event-driven server rather than a thread-per-request model. Long polling was the backbone of pre-WebSocket web chat and survives today as a fallback and in polling-based queue APIs, AWS SQS ReceiveMessage with WaitTimeSeconds=20 is exactly long polling.

Subtleties worth naming: requests must carry a cursor or last-event ID so nothing is missed in the gap between responses, and intermediaries with shorter idle timeouts than yours (load balancer idle timeout, commonly 60 seconds default on AWS ALB) will sever held connections, so the server timeout must be set below them.

Server-Sent Events

SSE is a one-directional stream from server to client over a single long-lived HTTP response with content type text/event-stream. The browser's built-in EventSource API handles it natively, including two things you get for free that WebSockets make you build: automatic reconnection, and resume via the Last-Event-ID header, the client reconnects and tells the server the last event it saw, so the server can replay the gap.

Because SSE is plain HTTP, it traverses proxies, corporate middleboxes, and L7 load balancers without special protocol handling, and works with standard HTTP auth and observability tooling. Over HTTP/1.1, browsers cap connections per origin at about 6, which SSE can exhaust, but over HTTP/2 streams multiplex on one connection and the problem disappears. The constraint is fundamental, though: server-to-client only; any client-to-server communication rides ordinary separate requests. It is also text-oriented (binary must be encoded).

SSE is the right tool when the data flows one way: notification feeds, live scores and tickers, progress updates, and notably LLM token streaming, the OpenAI and Anthropic APIs stream completions as SSE. A useful interview line: if clients mostly listen, SSE plus normal POSTs for the occasional upstream message is simpler and more robust than a WebSocket.

WebSockets

WebSockets provide a persistent, full-duplex, bidirectional channel. The client sends an HTTP request with Upgrade: websocket; after the 101 response, the TCP connection stops being HTTP and both sides exchange lightweight frames (text or binary) with 2-14 bytes of overhead, no per-message headers, at any time in either direction. This is the tool for genuinely interactive systems: chat (Slack), collaborative editing (Figma, Google Docs), multiplayer games, and live trading interfaces.

The engineering cost is state. Each connection holds server memory (tens of KB), and a server handles on the order of tens of thousands to hundreds of thousands of connections depending on message rates, so a million concurrent users means a fleet of connection servers and, critically, a routing problem: when user A messages user B, B's socket lives on some other server, so you need a pub/sub backplane, Redis pub/sub or Kafka, that connection servers subscribe to, plus a registry or topic scheme mapping users to servers. Load balancers must support the upgrade and have long idle timeouts, connections must be rebalanced gracefully during deploys, and both sides need heartbeats (ping/pong frames) to detect half-dead connections that TCP alone will not surface for minutes.

Clients must implement reconnection with backoff and message resync themselves, there is no built-in Last-Event-ID equivalent, which is why production systems layer a protocol on top (sequence numbers, acks, replay on reconnect) or use frameworks like Socket.IO that bundle heartbeats, rooms, and long-polling fallback. Managed options, AWS API Gateway WebSockets, Ably, Pusher, exist precisely because stateful connection fleets are operationally expensive.

WebRTC and Choosing Among Them

WebRTC is the odd one out: peer-to-peer, UDP-based, and designed for media. It gives browsers direct low-latency channels for audio, video, and arbitrary data (DataChannel) without relaying through your servers, which is how Google Meet, Discord voice, and browser file-transfer tools work. The catch is connection establishment: peers behind NATs cannot simply dial each other, so WebRTC needs a signaling channel (usually a WebSocket to your server) to exchange session descriptions, STUN servers to discover public addresses, and TURN relay servers as a fallback when NAT traversal fails, roughly 10-20 percent of connections end up relayed through TURN, which costs you bandwidth. For multi-party calls beyond a handful of peers, full mesh explodes quadratically, so real products use an SFU (selective forwarding unit) that receives each stream once and forwards it to others.

Use WebRTC when you need media or sub-100 ms peer latency; it is overkill for ordinary app real-time features, where its complexity buys nothing over a WebSocket through your backend.

The decision framework to recite: how fresh must data be, which directions does it flow, and at what scale? Updates every 30+ seconds: short polling. Server-push only: SSE, with its free reconnection and HTTP-friendliness. True bidirectional interaction: WebSockets, and budget for the stateful fleet and pub/sub backplane. Media or P2P: WebRTC with signaling, STUN/TURN, and an SFU. And regardless of primary choice, production systems keep a fallback path (Socket.IO's polling downgrade, or SSE falling back to polling) because some corporate networks still mangle upgraded or long-lived connections.

Key points

  • Short polling: simplest, works everywhere, latency is half the interval and most requests are empty; fine for 30s+ freshness.
  • Long polling: server holds the request until data or timeout; near-instant latency, but one open request per client and careful timeout alignment with load balancers (SQS WaitTimeSeconds is this pattern).
  • SSE: one-way server push over plain HTTP with free auto-reconnect and Last-Event-ID resume; ideal for feeds, tickers, and LLM token streaming.
  • WebSockets: full-duplex persistent connections for chat, collaboration, and games; requires a stateful connection fleet, pub/sub backplane, heartbeats, and reconnect logic.
  • WebRTC: P2P UDP for media and sub-100 ms latency; needs signaling, STUN/TURN (10-20 percent of sessions relay through TURN), and an SFU for group calls.
  • Ask three questions to choose: required freshness, direction of data flow, and connection scale; always keep a fallback transport.

Tradeoffs

Long polling vs WebSockets

Pros

  • + Long polling is plain HTTP: stateless-ish servers, standard LBs, easy auth, easy fallback
  • + Near-real-time latency without a persistent-connection fleet

Cons

  • Reconnect-per-event overhead makes high message rates inefficient
  • WebSockets are far cheaper per message but demand connection state, sticky routing, and a pub/sub backplane

SSE vs WebSockets

Pros

  • + SSE gives auto-reconnect with event replay (Last-Event-ID) out of the box and traverses HTTP infrastructure cleanly
  • + Simpler server model; works with HTTP/2 multiplexing

Cons

  • One-directional only; client-to-server messages need separate requests
  • Text-oriented; binary and truly interactive use cases need WebSockets

WebRTC P2P vs server-relayed delivery

Pros

  • + Lowest possible latency and zero media bandwidth through your servers when P2P succeeds
  • + Native browser support for audio, video, and data channels

Cons

  • NAT traversal complexity: signaling plus STUN/TURN, with TURN relay costs for 10-20 percent of sessions
  • Group scale requires SFU infrastructure; unnecessary complexity for non-media features

In the interview

  • Do not reflexively say WebSockets; walking through polling, SSE, and WebSockets and picking by direction, freshness, and scale is the senior move.
  • If you choose WebSockets, immediately address the hard part: connection state, routing messages across servers via Redis or Kafka pub/sub, heartbeats, and reconnection.
  • Estimate connection load: for example 10M concurrent users at 100k connections per server is a 100-server stateful fleet before redundancy.
  • Name SSE for one-way streams and cite LLM APIs or notification feeds; distinguishing SSE from WebSockets correctly is a common differentiator.

Related topics