WebSockets

How chat apps, live dashboards, and collaborative tools push updates without polling.

What HTTP cannot do

HTTP is request and response. The client asks. The server answers. The connection closes. The server cannot say anything unless asked first.

That is fine for fetching pages and API data. But what if the server wants to push something? "New message from your friend." "The price just changed." "Another user edited this doc."

The old workarounds were polling (the client asks every few seconds, "anything new?") and long polling (the client asks, the server holds the request open until something happens, then responds). Both are wasteful and laggy.

WebSockets fix this. They give you one long-lived connection that either side can send messages over at any time.

How a WebSocket connection starts

It starts as a normal HTTP request. The client sends a request with a special header. Upgrade: websocket.

If the server agrees, it sends back 101 Switching Protocols. From that moment on, the TCP connection is no longer HTTP. It is a raw two-way pipe.

Both the client and the server can send messages over it at any time. There is no request and response framing. Just a stream of messages.

You see this in real apps everywhere. Slack. Discord. Google Docs. Trello. Twitch chat. All of them use WebSockets for their real-time features.

The browser API is simple. const ws = new WebSocket("wss://..."). Then ws.send(...) to send and ws.onmessage to receive.

The cost of running them

WebSockets are great, but they are stateful. The server holds one open connection per user. 10,000 users means 10,000 open connections.

This breaks some of the assumptions of regular horizontal scaling.

You cannot just round-robin requests across servers anymore. Each user is pinned to the server that holds their connection. Restarting a server kills all its connections. Users have to reconnect. Cross-server messaging is hard. User A is on Server 1. User B is on Server 2. To push a message to A about B's action, Server 2 needs a way to find A. The usual answer is a pub/sub system like Redis or Kafka that connects all the WebSocket servers.

A real setup looks like this. WebSocket servers behind a layer 4 (TCP) load balancer with sticky sessions. Plus a Redis pub/sub backbone for cross-server fan-out.

When to use them and when not to

Use WebSockets when updates need to feel instant. Chat. Live cursors. Multiplayer games. When the server has to push events the client did not ask for. When you have many small messages going both ways during a session.

Do not use WebSockets when you are just fetching data every few seconds. Plain HTTP is fine. When the data flow is mostly request and response. Use HTTP. When you cannot afford the extra complexity. Use Server-Sent Events for server-to-client only, which is simpler.

Some alternatives. SSE (Server-Sent Events) is for one-way server to client streaming. HTTP long polling is fine for low-frequency updates. WebRTC is for peer-to-peer cases like video calls and file transfer.

WebSockets are the right tool for chat-style apps. Do not reach for them just because real-time sounds cool.

Now build it yourself →