Real-time server-to-client communication requires the server to push data without waiting for a client request. Three primary patterns exist: long polling (HTTP-based hack), Server-Sent Events (one-way HTTP streaming), and WebSockets (full-duplex TCP). Each has distinct trade-offs in complexity, browser compatibility, proxy support, and scalability that determine which is appropriate for a given use case.
Long Polling
The client sends an HTTP request. The server holds the request open until it has data to send (or a timeout occurs). When the server responds, the client immediately sends a new request. This simulates server push using standard HTTP. Advantages: works with any HTTP infrastructure (proxies, load balancers, CDNs), no special server support needed, works everywhere HTTP works. Disadvantages: one in-flight HTTP request per client (each consuming a thread or file descriptor on the server), HTTP overhead per message (headers re-sent on each round trip), latency is RTT + server processing time (not zero like WebSockets). Use long polling when: WebSockets are blocked by corporate proxies, the message rate is low (< 1/minute), or infrastructure constraints preclude persistent connections.
Server-Sent Events (SSE)
SSE uses a persistent HTTP connection where the server sends a stream of events using the text/event-stream content type. The browser’s EventSource API handles reconnection automatically. Messages are plain text with a simple format: data: {message}nn. SSE is one-way — server to client only. Advantages: simple protocol (plain HTTP), automatic reconnection built into the browser, works through HTTP/2 multiplexing (multiple SSE streams over one TCP connection), proxies handle it well. Disadvantages: one-way only (no client-to-server messages without a separate HTTP request), limited browser connection pool (browsers allow ~6 concurrent SSE connections per domain). Use SSE for: live dashboards, activity feeds, notifications, progress tracking — any use case where server pushes updates to a passive client.
WebSockets
WebSockets upgrade an HTTP connection to a full-duplex binary or text protocol. The handshake uses HTTP Upgrade headers; after the handshake, the protocol is WebSocket frames — not HTTP. Both sides can send at any time. Advantages: full-duplex (client and server both send), binary support (efficient for audio, video, game state), very low overhead per message (2-6 byte framing overhead vs. hundreds of bytes of HTTP headers), sub-millisecond latency. Disadvantages: not HTTP — many corporate proxies and firewalls block WebSockets or add buffering; requires WebSocket-aware load balancers (sticky sessions or consistent routing); harder to scale horizontally (persistent connections are stateful). Use WebSockets for: chat applications, collaborative editing, multiplayer games, live trading — any use case requiring high-frequency bidirectional communication.
Scaling Persistent Connections
WebSocket and SSE connections are long-lived and stateful — they are pinned to one server. Load balancing requires either: sticky sessions (all requests from a client go to the same server — creates hot spots), or a pub/sub layer (each server subscribes to a shared message bus; when a message must be sent to a client, any server can publish it and the server holding the client’s connection delivers it). The pub/sub approach (Redis Pub/Sub, Kafka) decouples connection management from message delivery, enabling horizontal scaling without sticky sessions.
Choosing the Right Pattern
Decision framework: If the use case is server-to-client only and message rate is low (notifications, activity feeds, dashboards) → use SSE. If the use case requires bidirectional communication or high message frequency (chat, games, collaborative editing) → use WebSockets. If WebSockets are blocked by proxy/firewall constraints → use long polling as a fallback (Socket.io handles this transparently, starting with long polling and upgrading to WebSockets when available). If the client does not need real-time updates but benefits from data being fresh when requested → use polling with a short interval (30 seconds) rather than persistent connections.
See also: Meta Interview Guide 2026: Facebook, Instagram, WhatsApp Engineering
See also: Uber Interview Guide 2026: Dispatch Systems, Geospatial Algorithms, and Marketplace Engineering
See also: Scale AI Interview Guide 2026: Data Infrastructure, RLHF Pipelines, and ML Engineering
See also: Airbnb Interview Guide 2026: Search Systems, Trust and Safety, and Full-Stack Engineering
See also: Databricks Interview Guide 2026: Spark Internals, Delta Lake, and Lakehouse Architecture
See also: Anthropic Interview Guide 2026: Process, Questions, and AI Safety
See also: Atlassian Interview Guide
See also: Coinbase Interview Guide
See also: Shopify Interview Guide
See also: Snap Interview Guide
See also: Lyft Interview Guide 2026: Rideshare Engineering, Real-Time Dispatch, and Safety Systems
See also: Stripe Interview Guide 2026: Process, Bug Bash Round, and Payment Systems