API Styles Deep Dive · 4 of 7

WebSockets — The Always-On Two-Way Pipe

A WebSocket starts as an HTTP request with an Upgrade header, then turns the underlying TCP connection into a full-duplex frame channel. Both sides push whenever they want, no polling, no reconnecting per message. It's the right tool when both sides genuinely have things to say to each other in real time — and overkill for most other things.

Full-DuplexPersistentReal-TimeChatMultiplayer
← Back to APIs & Networking
Quick Facts

What WebSockets Are

Basic Concepts

  • Standardized: RFC 6455 (2011). Native in every browser, every server platform, every mobile runtime.
  • Handshake: client sends an HTTP GET with Upgrade: websocket; server replies 101 Switching Protocols; the TCP socket then carries WebSocket frames instead of HTTP messages.
  • Full-duplex: either side can send any time. No request/response coupling.
  • Frames: binary or UTF-8 text. The protocol does framing and pings; you put your own JSON or binary inside.
  • URLs: ws:// (plain) or wss:// (TLS). Always use wss:// in production.
  • Subprotocols: the handshake can negotiate a protocol on top — STOMP, MQTT-over-WebSocket, GraphQL subscriptions, your own.
Why It Wins

What You Buy

Real-Time, Both Ways

A typing indicator, a cursor moving in a shared doc, a price tick, a chess move — anything where either side wants to push instantly and the other side wants to react. Polling that 100× per second would be brutal; with WebSockets it's one open connection and a handful of frames per second.

Low Per-Message Overhead

HTTP/1.1 sends headers on every request — a few hundred bytes minimum. A WebSocket frame is 2–14 bytes plus the payload. For high-frequency tiny messages (cursors, ticks, presence heartbeats), that's a 50–100× reduction in overhead.

Universal Browser Support

Native WebSocket API in every browser since IE 10. No polyfills. No flash fallbacks. Same on iOS, Android, desktop runtimes.

Where It Hurts

The Real Operational Pain

Connections Die

Mobile networks drop. Wi-Fi switches. Corporate proxies kill idle TCP after a few minutes. You need:

  • Application-level pings/heartbeats every 20–30s.
  • Auto-reconnect with exponential backoff and jitter.
  • A way to resume — message IDs the server can replay from.
  • Graceful UI degradation when reconnecting.
Scaling Across Servers

A WebSocket is bound to one server process. If user A is connected to server 1 and user B to server 2, and A sends B a message, server 1 can't deliver it directly. You need a fan-out backplane — Redis pub/sub, Kafka, NATS, a cloud broker — that all servers subscribe to. Building this after the connection count grows is painful.

Sticky Sessions on Load Balancers

The HTTP Upgrade handshake hits a load balancer; the long-lived TCP connection that follows must keep going to the same backend. Configure session affinity (or use a TCP/L4 load balancer for WebSocket traffic). Sticky sessions complicate blue/green deploys — drain connections gracefully.

Back-Pressure

What if the server pushes faster than a slow consumer can read? Frames buffer in the OS socket; the buffer fills; the server's writes block. Without explicit back-pressure (drop, coalesce, slow down), one bad client can pin a thread or a connection forever.

Authentication Is Awkward

The browser WebSocket API doesn't let you set custom headers, so the typical "Authorization: Bearer ..." pattern doesn't work. Options: pass the token as a query param (visible in logs), authenticate after connection on the first frame, or use a short-lived ticket your REST API issues just for the WebSocket handshake.

No Built-in Versioning, Schema, or Caching

WebSockets are a transport, not a contract. You bring your own schema (Protobuf, Avro, JSON Schema), your own versioning, your own validation. Caches and CDNs don't help — every byte goes back to your origin.

Use Cases

Where WebSockets Are the Right Answer

Use CaseWhy WebSockets
Chat & messagingBoth sides push; messages need to arrive instantly.
Multiplayer gamesFrequent tiny updates from many players; latency matters.
Collaborative editing (cursors, edits)Sub-100ms presence and operational-transform updates.
Trading dashboardsHigh-frequency price ticks, order book updates.
Live ops dashboards / observabilityStream metrics and events as they happen.
IoT command + telemetryDevices push sensor data; server pushes commands back.

For one-way server-to-client streams (notifications, log tail, AI token streaming), Server-Sent Events are simpler and survive proxies more reliably. For request/response with occasional pushes, REST + SSE often beats WebSockets on operational simplicity.

Decision

When to Pick WebSockets

Pick WebSockets when you genuinely need a persistent two-way channel and the team is ready to operate one — heartbeats, reconnect logic, a cross-node fan-out backplane, sticky sessions, capacity planning by connection count, not by RPS.

Otherwise, prefer SSE for one-way streams or polling/long-polling for occasional pushes. Many "we need WebSockets" requirements are actually "we need to push a few events per minute," which doesn't justify the operational tax.

Continue

Other API Styles