WebSocket Heartbeats and the HTTP Upgrade Boundary

2026-11-03

A conventional HTTP/1.1 WebSocket connection begins as an HTTP request that asks to upgrade the protocol. The server validates the handshake and responds with status 101 when it accepts the upgrade. Afterward, the connection carries WebSocket frames rather than ordinary HTTP request and response messages.

In Node.js, upgrade handling is a distinct boundary from normal request handling. Before accepting a socket, an application should validate the intended route, authentication requirements, and any applicable origin policy. Origin checks can help protect browser-based sessions but are not a substitute for authentication, since non-browser clients can supply their own headers.

An open socket does not necessarily mean the remote peer is reachable. Network changes, silent connection loss, and intermediary idle timeouts can leave either side waiting without a prompt close notification. A heartbeat sends a liveness probe and requires a response within a defined interval, allowing the service to retire connections that no longer respond.

WebSocket ping and pong are protocol control frames. Browser JavaScript cannot directly send those control frames, although browser implementations handle protocol pings internally. Applications can also define message-level heartbeats, but those messages need an agreed format and should not be confused with protocol ping and pong behavior.

Heartbeat intervals must leave room for ordinary latency and event-loop delays without keeping dead connections forever. Timers should be cleared when connections close, and buffered outbound data should be bounded so a slow peer cannot consume unlimited memory. Proxies must support upgrades and suitable idle timeouts; a heartbeat does not repair an unsupported upgrade path or replace flow control.