WebSockets vs SSE vs long polling for real-time. — Cracked Java
// High-Level Design (HLD / Distributed Systems) · API Design — REST, gRPC, GraphQL, WebSockets
MidSystem Design

WebSockets vs SSE vs long polling for real-time.

WebSockets vs SSE vs long polling for real-time

Plain HTTP is request/response — the client must ask before the server can answer. "Real-time" means the server pushes when something changes. There are three mainstream ways to get push semantics over the web, in increasing capability and cost.

The three transports

Long pollingSSEWebSockets
Directionserver→client (per request)server→client (one stream)full-duplex
Protocolplain HTTPHTTP (text/event-stream)ws:// upgrade from HTTP
Connectionmany short requestsone long-lived HTTP responseone long-lived TCP socket
Auto-reconnectn/a (client re-requests)built in (browser)manual
Binaryyesno (text only)yes
Proxy/firewall friendlinessbestgoodsometimes blocked
Server costhigh (constant reconnects)lowlow

Long polling — the compatible fallback

The client makes a request; the server holds it open until it has data (or a timeout), responds, and the client immediately reconnects. It needs no special protocol, so it works through any proxy and old browser. The cost is overhead and latency: a flood of reconnections, header re-sending each time, and a window between responses where events queue. Use it only as a fallback when WebSockets/SSE aren't available.

SSE (Server-Sent Events) — one-way stream, cheap and robust

The server keeps a single HTTP response open and streams text/event-stream frames. It's unidirectional (server→client only), text-only, and runs over ordinary HTTP — so it traverses proxies cleanly and the browser reconnects automatically and resumes from the Last-Event-ID. Perfect for feeds, notifications, live scores, dashboards, LLM token streaming — anywhere the client mostly listens.

WebSockets — full-duplex, the heavy hitter

A WebSocket upgrades an HTTP connection to a persistent, bidirectional TCP channel; both sides send frames anytime, text or binary, with minimal per-message overhead. It's the right tool for chat, multiplayer games, collaborative editing, live trading — anything with frequent client→server and server→client traffic.

Costs to call out:

  • Stateful connections. Each socket pins a client to a server, which complicates load balancing and horizontal scaling — you need a pub/sub backplane (e.g. Redis) so any server can deliver a message regardless of which one holds the socket.
  • No free reconnect/heartbeat. You implement ping/pong and reconnection yourself.
  • Infra friction. Some proxies/load balancers need explicit WebSocket support; L7 LBs must handle the upgrade.
Choosing a real-time transport

Decision rule

  • Mostly server→client push → SSE (cheap, auto-reconnect, proxy-friendly).
  • Frequent two-way traffic → WebSockets (plan for the pub/sub backplane and sticky/aware routing).
  • Need to work through hostile networks or legacy clients → long polling as the graceful fallback.

Mark your status