WebSockets
Updated June 6, 2026Imagine trying to have a phone conversation using a system where only one person can call the other, and after each sentence you have to hang up and wait to be called back. That's roughly what HTTP-based communication feels like for real-time apps. WebSockets fix this.
WebSockets give you a persistent, full-duplex connection between client and server. Both sides can send messages at any time, independently, without waiting for the other to ask. It's a real conversation, not a series of phone tags.
The WebSocket Handshake
Here's something that surprises most people: WebSocket connections start as HTTP.
The client sends a regular HTTP request with a special header:
GET /chat HTTP/1.1
Host: chat.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13If the server supports WebSockets, it responds with:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=That 101 Switching Protocols is the upgrade moment. The TCP connection that carried the HTTP request is now handed over to the WebSocket protocol and it stays open. From this point on, both client and server communicate using lightweight WebSocket frames, not HTTP.
WebSocket handshake — HTTP upgrade to persistent full-duplex connection
This upgrade handshake is clever for a few reasons. It means WebSockets work on port 80 and 443 (the same ports as HTTP and HTTPS), so they pass through most firewalls and proxies without special configuration.
What HTTP status code signals that a WebSocket upgrade was accepted, and what does it mean?
Full-Duplex: Both Sides Talk Freely
With WebSockets, the server doesn't need to wait for the client to ask before sending data. When something happens, a new chat message, a stock price change, a collaborative edit, the server pushes it immediately.
The client can send messages whenever it wants too.
This is fundamentally different from long polling, where:
- The client always initiates
- The server can only respond (never push first without a waiting request)
- There's connection overhead on every reconnect
With WebSockets, you pay the handshake cost once. Everything after that is low-overhead framing.
Use Cases That Actually Need WebSockets
Not every feature needs WebSockets. But when they're the right tool, they're really the right tool.
Real-Time Chat
Slack, Discord, and WhatsApp Web all need sub-second message delivery. Long polling's reconnect overhead would noticeably degrade the experience at scale.
Live Collaboration
Figma is a great example. When you move an object, every collaborator sees it move in real time. That requires the server to push your cursor position and edits to dozens of other clients simultaneously, continuously.
Trading Dashboards and Live Data Feeds
Financial platforms like Robinhood and Bloomberg push real-time price quotes, order book updates, and trade confirmations. Latency matters here — a stale price quote for even a few seconds can mean bad trades.
Multiplayer Games
Game state (player positions, scores, events) must be synchronized across clients in near real-time.
Live Dashboards
DevOps monitoring tools, real-time analytics boards, live delivery tracking, anything where data changes faster than a reasonable polling interval.
Scaling WebSockets: The Hard Part
Here's where things get interesting, and where WebSockets differ most from stateless HTTP.
HTTP servers are naturally stateless. Any server can handle any request. You can add or remove servers and a load balancer distributes traffic cleanly.
WebSockets are stateful. A connection lives on a specific server. That server holds the state of that connection — the user's session, subscriptions, any in-memory data. If the user's next message hits a different server, it doesn't have that context.
Sticky Sessions
The simplest solution is sticky sessions (also called session affinity). The load balancer looks at a cookie or IP address and ensures all requests from a given client always go to the same server.
This works, but it's fragile. If that server goes down, all its connections are lost. And it makes it harder to rebalance traffic across servers.
Connection Brokers / Message Buses
A more robust approach: use a shared pub/sub layer (like Redis Pub/Sub or Kafka) so that all WebSocket servers can communicate.
When a message needs to go to user A, the server handling it publishes to Redis. Every WebSocket server subscribes to that channel. The server that holds user A's connection picks it up and delivers it.
Scaling WebSockets with Redis Pub/Sub — messages route between servers
This is how Slack, Discord, and most large-scale WebSocket systems actually work. Your connection might be on Server 3, but a message from someone on Server 7's connection reaches you because both servers share a message bus.
Why do WebSockets require sticky sessions (or a message bus) when scaled horizontally?
Horizontal Scaling with a Gateway
Many modern systems put a dedicated WebSocket gateway in front of the application servers. The gateway handles connection state, and the application servers remain stateless. This is the pattern used by services like Pusher and Ably.
WebSockets vs the Alternatives
| WebSockets | Long Polling | Server-Sent Events | |
|---|---|---|---|
| Direction | Full-duplex | Client-initiated | Server-to-client only |
| Connection | Persistent | Reconnects per event | Persistent (one-way) |
| Protocol | WS/WSS | HTTP | HTTP |
| Browser support | Excellent | Excellent | Good (not IE) |
| Load balancing | Harder (sticky sessions) | Easy (stateless) | Medium |
Server-Sent Events (SSE) are worth knowing about too. They're a simpler alternative when you only need server-to-client push (no client-to-server streaming). SSE works over plain HTTP/2, handles reconnection automatically, and avoids the sticky session problem. Good for live notifications and AI-streaming responses.
When should you choose Server-Sent Events (SSE) over WebSockets?
Real-World Examples
- Slack: WebSockets for message delivery, presence updates (online/away status), and typing indicators
- Figma: WebSockets for real-time collaborative editing and cursor positions
- Robinhood / Coinbase: WebSockets for live price feeds and portfolio updates
- Google Docs: Operational transforms over WebSockets for collaborative editing
- GitHub: WebSockets for live notification feeds and pull request activity
Summary
WebSockets give you a persistent, full-duplex channel between client and server, established via an HTTP Upgrade handshake and maintained as a long-lived TCP connection. They're the right choice for real-time chat, live collaboration, trading feeds, and multiplayer games. The main scaling challenge is their statefulness: unlike HTTP, WebSocket connections are tied to specific servers, which requires sticky sessions or a shared message bus to scale horizontally. At large scale, systems like Slack and Discord solve this with a pub/sub layer (typically Redis) that allows any server to relay messages to any connected client.
How helpful was this content?
Comments
Sign in to join the discussion
Saved on this device only
Sign in to sync progress across devices