WebSocket

What is a WebSocket?

WebSocket is a communication protocol that establishes a persistent, bidirectional connection between a client (typically a browser) and a server. Unlike HTTP, where the client must send a request to receive a response, WebSocket allows both the client and server to send messages at any time, independently, over a single long-lived connection. The connection starts as an HTTP request -- the "handshake" -- and then upgrades to the WebSocket protocol, remaining open until either side explicitly closes it.

This persistent connection eliminates the overhead of repeatedly establishing and tearing down HTTP connections. Once the WebSocket handshake completes, messages flow freely in both directions with minimal latency and no per-message headers. The protocol is standardized (RFC 6455) and supported by all modern browsers.

Why does it matter?

Many modern applications require real-time data. Chat messages, live notifications, collaborative editing, stock price updates, IoT sensor readings, multiplayer game states -- these features demand that the server push data to the client the instant it becomes available. HTTP was not designed for this. The traditional workarounds -- polling (asking the server for updates every few seconds) and long-polling (holding a request open until data is available) -- are inefficient and introduce latency.

Polling wastes bandwidth and server resources. A client checking for new messages every 2 seconds generates 1,800 requests per hour, most of which receive empty responses. Long-polling reduces unnecessary requests but ties up server connections and introduces latency equal to the round-trip time for each new piece of data. Neither approach scales elegantly to thousands of concurrent users.

WebSocket solves this cleanly. One connection per client, maintained for the duration of the session, with messages delivered in milliseconds. A chat application with 10,000 concurrent users maintains 10,000 WebSocket connections rather than handling 18 million polling requests per hour. The server pushes messages the instant they are created, with no waiting for the next poll interval. For real-time features, the user experience difference is immediately perceptible.

The business impact extends beyond user experience. Real-time features -- live dashboards, instant notifications, collaborative tools -- are increasingly expected by users. Applications that update only on page refresh feel outdated. A project management tool where task status updates appear instantly across all team members' screens provides a fundamentally different experience than one where users must manually refresh to see changes. WebSocket enables these experiences efficiently and reliably.

WebSocket in practice

Implementing WebSocket involves both server-side and client-side components. On the server, Node.js is particularly well-suited for WebSocket applications because of its event-driven, non-blocking architecture. Libraries like Socket.IO and ws provide the server-side infrastructure. Socket.IO adds features like automatic reconnection, room-based broadcasting, and fallback to polling for environments where WebSocket is not available.

A typical real-time notification system works as follows: the user logs into a React application, and the client establishes a WebSocket connection to the server, authenticated with the user's session token. The server registers the connection in a connection map. When an event occurs that affects the user -- a new order, a team mention, a system alert -- the backend service publishes an event. The WebSocket server receives the event, looks up the connected users who should be notified, and pushes the message through their WebSocket connections. The client receives the message and updates the UI instantly, without any user action.

For GraphQL applications, WebSocket is the transport layer for subscriptions. A client subscribes to a query -- for example, subscription { orderUpdated(id: "123") { status estimatedDelivery } } -- and the server pushes updates through the WebSocket connection whenever the subscribed data changes. This provides a type-safe, schema-driven approach to real-time data that integrates cleanly with the rest of the GraphQL API.

Scaling WebSocket applications requires consideration that stateless HTTP applications do not face. WebSocket connections are stateful -- each connection is tied to a specific server process. When running multiple server instances behind a load balancer, a message published on one server must reach clients connected to other servers. Solutions include a shared pub/sub layer (Redis Pub/Sub, Kafka, or Redpanda) that distributes messages across all server instances, and sticky sessions that route reconnecting clients back to their original server.

Connection management is critical for production reliability. Clients must handle disconnections gracefully -- network changes, server restarts, mobile devices going to sleep. Automatic reconnection with exponential backoff, heartbeat pings to detect dead connections, and message queuing during disconnections ensure that the real-time experience remains reliable even on unstable networks.

Security considerations include authenticating WebSocket connections (typically via a token in the handshake or first message), authorizing subscriptions (ensuring users only receive data they are permitted to see), and rate limiting to prevent abuse. In multi-tenant applications, tenant isolation extends to WebSocket channels -- messages for Tenant A must never reach Tenant B's connections.

Related concepts

We respect your privacy

This website uses cookies for essential functions and optionally for analytics and marketing. Privacy Policy