HTTP is fundamentally request-then-response — the server can never speak first. WebSockets flip that: one handshake upgrades a plain HTTP connection into a persistent, full-duplex channel either side can write to, whenever it wants.
3 min read
Regular HTTP is strictly request-response — the client always initiates, and the server can only ever reply to something it was asked. That's a real problem for anything that needs the server to push data the instant something happens: a chat message from another user, a live stock price tick, a multiplayer game state update. Before WebSockets, this was faked with polling (the client asks "anything new?" every few seconds — wasteful and still not instant) or long polling (the server holds the request open until it has something to say, then the client immediately reopens it) — real approaches still used today where a persistent connection isn't worth the complexity.
A WebSocket connection starts as a completely normal HTTP request, with headers that ask to switch protocols on the very same already-open TCP connection:
GET /chat HTTP/1.1
Host: example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
That 101 Switching Protocols status is the moment the connection stops being
HTTP and becomes a raw, persistent, full-duplex WebSocket — reusing the exact
same already-established TCP connection (and its already-completed TLS handshake
if this is wss://) rather than paying either cost again.
Once upgraded, either side can send a message at any time, with no request-response pairing required at all:
Notice the server sends two messages in a row with no client request in between — something plain HTTP simply cannot express, and exactly the capability chat, live dashboards, collaborative editors, and multiplayer games actually need.
A WebSocket connection is held open for its entire lifetime — potentially hours — which means the server holding it must keep that connection's state in memory the whole time. This breaks the stateless-request assumption from the HTTP lesson: if a client's WebSocket connection is on Server A, a message meant for that client has to reach Server A specifically, not just any server behind the load balancer. Real systems solve this either by routing (sticky sessions pinning a client to one server) or by fanning messages out through a shared layer (commonly Redis pub/sub) so any server holding a relevant connection can receive and forward the message regardless of which server originally handled it.
Not every "needs to feel live" feature needs a WebSocket. If updates are
infrequent (a dashboard refreshing every 30 seconds is fine with regular polling
or Cache-Control tuning) or one-directional (server-to-client only), Server-
Sent Events (SSE) — a simpler, HTTP-native one-way stream — is often the better
fit: no special upgrade handshake, works over plain HTTP/2 multiplexing, and
degrades more gracefully through restrictive networks/proxies that sometimes
block WebSocket upgrades outright. Reach for a WebSocket specifically when the
client also needs to send messages at arbitrary times, not just receive them.
Check your understanding
A quick comprehension check — not tracked, not graded, just for you.
1. What can a WebSocket do that a regular HTTP request-response cycle cannot?
2. How does a WebSocket connection begin, technically?
3. Why do WebSocket connections complicate load balancing compared to stateless HTTP requests?
Networking Fundamentals