How Do WebSockets Work?

How Do WebSockets Work?

User Avatar

Quick reference: How do Websockets work?

Question Answer
What is a WebSocket? A protocol that provides full-duplex communication over a single TCP connection.
How do WebSockets start? With an HTTP handshake that upgrades to the WebSocket protocol.

Can servers send messages first?

Yes, after the connection is established, either party can send messages at any time.
Are WebSockets encrypted? Use WSS (WebSocket Secure) for TLS encryption, like HTTPS.
Do WebSockets work with load balancers? Yes, but they often require session affinity so messages from a client stay on the same server.
How do you close a WebSocket? Either party sends a close frame, triggering a closing handshake.
What’s the difference between WebSocket and HTTP? WebSockets are persistent and bidirectional, while HTTP follows a request-response pattern.
When should I use WebSockets? For real-time, bidirectional communication with low latency requirements.


Try Postman today →

WebSockets introduce a different communication model than standard HTTP. After an initial HTTP handshake, the connection is upgraded and maintained, allowing for ongoing, bidirectional message exchange over a single TCP connection. This approach reduces latency and overhead for applications that need real-time interaction.

This guide explains how WebSockets work under the hood, from the initial connection to ongoing message exchange, and when you should choose WebSockets over traditional HTTP.

What are WebSockets?

WebSockets are a communication protocol that provides full-duplex (bidirectional) communication channels over a single TCP connection. Unlike HTTP, where the client must always initiate requests, WebSockets allow both the client and server to send messages to each other at any time once the connection is established.

Think of HTTP like sending letters through the mail. Every time you need information, you send a request letter and wait for a response. WebSockets are more like having an open phone line, where both parties can speak whenever they have something to say, without having to hang up and redial.

The WebSocket protocol operates on top of TCP and is designed to work over HTTP ports 80 and 443, making it compatible with existing network infrastructure.

The WebSocket connection lifecycle

Understanding how WebSockets work requires following the complete connection lifecycle, from initial handshake to message exchange and eventual closure.

The opening handshake

Every WebSocket connection begins with an HTTP request. The client sends a standard HTTP request with special headers, requesting an upgrade to the WebSocket protocol.

Here’s what a WebSocket handshake request looks like:

GET /chat HTTP/1.1
Host: example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13
Origin: https://example.com

The key headers in this request are:

  • Upgrade: websocket: Asks the server to upgrade from HTTP to WebSocket

  • Connection: Upgrade: Indicates this is an upgrade request

  • Sec-WebSocket-Key: A randomly generated base64-encoded value for security

  • Sec-WebSocket-Version: The WebSocket protocol version (13 is current)

If the server supports WebSockets and accepts the upgrade, it responds with:

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=

The 101 Switching Protocols status code confirms the protocol change. The Sec-WebSocket-Accept header contains a hash derived from the client’s Sec-WebSocket-Key, which proves that the server understands the WebSocket protocol.

After both sides complete the handshake, the HTTP connection is transformed into a WebSocket connection. The same TCP socket remains open, but now it follows WebSocket protocol rules instead of HTTP.

Message exchange

After the handshake completes, both client and server can send messages through the open connection at any time. This bidirectional communication happens without the overhead of HTTP headers on every message.

WebSocket messages consist of one or more frames. Each frame includes:

  • FIN bit: Indicates if this is the final frame in a message

  • Opcode: Specifies the frame type (text, binary, close, ping, pong)

  • Mask bit: Client-to-server frames must be masked for security

  • Payload length: Size of the message data

  • Payload data: The actual message content

Here’s a simple example showing bidirectional messaging:

// Client creates WebSocket connection
const socket = new WebSocket('wss://example.com/chat');

// Connection established
socket.onopen = () => {
  console.log('Connected to server');
  socket.send('Hello from client!');
};

// Receiving messages from server
socket.onmessage = (event) => {
  console.log('Server says:', event.data);
  // Server can send messages anytime
};

// Sending messages to server
function sendMessage(text) {
  socket.send(text);
}

The server can similarly send messages whenever needed:

// Server-side (Node.js with ws library)
wss.on('connection', (ws) => {
  console.log('Client connected');
  
  // Server can send messages anytime
  ws.send('Welcome to the chat!');
  
  // Receiving messages from client
  ws.on('message', (data) => {
    console.log('Client says:', data);
    // Broadcast to all connected clients
    wss.clients.forEach((client) => {
      if (client.readyState === WebSocket.OPEN) {
        client.send(data);
      }
    });
  });
});

This bidirectional capability enables the server to push updates to clients without waiting for requests, allowing for true real-time communication.

Connection maintenance and closing

WebSocket connections remain open indefinitely until they’re explicitly closed or disrupted. The protocol includes ping and pong frames to detect connection problems. The server or client can send a ping frame, and the recipient must respond with a pong. If no response arrives within a timeout period, the connection is considered dead.

Either party can close the connection by sending a close frame with an optional status code and reason:

// Client initiates close
socket.close(1000, 'Normal closure');

// Handle close event
socket.onclose = (event) => {
  if (event.code !== 1000) {
    // Abnormal closure, try to reconnect
    setTimeout(reconnect, 5000);
  }
};

Common close codes include 1000 (normal), 1001 (going away), 1002 (protocol error), and 1006 (abnormal closure).

How WebSockets differ from HTTP

Communication pattern

HTTP follows a request-response pattern where clients initiate all interactions. WebSockets maintain persistent connections, allowing either party to send messages at any time.

Connection overhead

HTTP requests include hundreds of bytes of header overhead on every request. After the initial handshake, WebSocket messages have just 2-6 bytes of framing overhead.

Latency

HTTP requires full round trips for every interaction. WebSockets eliminate this latency for subsequent messages after the connection is established.

Scaling

HTTP’s stateless nature makes horizontal scaling straightforward. WebSocket connections are stateful, requiring session affinity in load-balanced environments.

WebSocket use cases

WebSockets excel in scenarios requiring real-time, bidirectional communication:

Chat and messaging

Slack and Discord deliver messages instantly by pushing them through WebSocket connections rather than making clients poll for updates.

Collaborative editing

Google Docs and Figma broadcast document changes to all active editors through WebSocket connections, ensuring everyone sees updates within milliseconds.

Live dashboards

Trading platforms and monitoring tools stream metrics, prices, and system status updates in real time, eliminating the need for manual refreshing.

Gaming

Multiplayer browser games synchronize player positions, actions, and game state through low-latency WebSocket connections.

Notifications

Social media platforms push likes, comments, and messages instantly over WebSocket connections instead of requiring page refreshes.

WebSocket security considerations

Always use WSS (WebSocket Secure)

Just as you should use HTTPS, always use WSS for WebSocket connections. WSS encrypts all communication using TLS, protecting against eavesdropping and tampering.

// Good: Secure WebSocket
const socket = new WebSocket('wss://example.com/chat');

Validate origin and implement authentication

Servers should validate the Origin header during handshake to prevent unauthorized connections. Pass authentication tokens during the initial handshake or in the first message:

// Pass token in handshake URL
const token = localStorage.getItem('authToken');
const socket = new WebSocket(`wss://example.com/chat?token=${token}`);

Rate limiting and message validation

Implement rate limiting to prevent abuse and validate all incoming messages. Limit message sizes and validate data structures to prevent the transmission of malicious payloads.

Testing WebSocket connections in Postman

Postman provides built-in support for testing WebSocket connections, making it easy to debug and verify WebSocket implementations.

To test a WebSocket connection:

  1. Click NewWebSocket Request.

  2. Enter your WebSocket URL (wss://example.com/chat).

  3. Click Connect to establish the connection.

  4. Send messages through the message input field.

  5. View sent and received messages in the message log.

  6. Use the connection status indicator to monitor the connection state.

You can also add connection parameters, custom headers, and authentication to your WebSocket requests. Postman displays the complete handshake exchange, making it easy to debug connection issues. For repeatable testing, you can organize WebSocket message flows in collections and validate responses programmatically.

When to choose WebSockets over HTTP

WebSockets aren’t always the right choice. Consider WebSockets when your application needs:

  • Real-time requirements. Data must appear immediately without polling delays. Chat applications, live feeds, and collaborative tools benefit from instant updates.

  • Bidirectional communication. The server needs to push data to clients without waiting for requests. Notifications, alerts, and event-driven architectures work well with WebSockets.

  • High-frequency messaging. Many small messages are exchanged between the client and server. The reduced overhead of WebSockets improves efficiency compared to repeated HTTP requests.

  • Low latency. Response time matters more than request-response clarity. Gaming, trading platforms, and real-time monitoring need minimal delays.

Stick with HTTP when:

  • Request-response interactions are sufficient. Most CRUD operations work fine with REST APIs.

  • Caching matters. Responses can be cached by CDNs or browsers. HTTP’s stateless nature makes caching straightforward.

  • Scaling is critical. You need to scale horizontally without session affinity. HTTP’s statelessness simplifies load balancing.

  • SEO is important. Search engines need to crawl your content. HTTP responses are indexable, while WebSocket messages aren’t.

Best practices for WebSocket implementations

Implement reconnection logic

Network disruptions happen. Your client code should detect connection loss and automatically reconnect with exponential backoff.

function connectWebSocket() {
  const socket = new WebSocket('wss://example.com/chat');
  let reconnectDelay = 1000;
  
  socket.onclose = () => {
    setTimeout(() => {
      reconnectDelay = Math.min(reconnectDelay * 2, 30000);
      connectWebSocket();
    }, reconnectDelay);
  };
  
  socket.onopen = () => {
    reconnectDelay = 1000; // Reset on successful connection
  };
}

Handle connection state and message queuing

Track connection state, disable UI elements when disconnected, and queue messages sent while offline for resending after reconnection. This prevents message loss during temporary network issues.

Monitor connection health

Implement heartbeat mechanisms to detect dead connections. Send ping frames or application-level keepalive messages to verify the connection remains alive, and close stale connections gracefully.

Common WebSocket mistakes

  • Not handling disconnections. Always implement reconnection logic and handle close events. Connections don’t stay open forever.

  • Sending too much data. Use HTTP for large file transfers. WebSockets work best for small, frequent messages.

  • Ignoring backpressure. Monitor send queue length and slow down when buffers fill up to prevent connection failures.

  • Poor error handling. Implement onerror handlers and log errors for debugging connection issues.

  • Forgetting about proxies. Corporate firewalls may block WebSocket connections. Provide fallback mechanisms for restricted environments.

Final thoughts

WebSockets provide a persistent, bidirectional communication channel that eliminates the request-response limitations of HTTP. By upgrading an initial HTTP connection and keeping it open, they allow clients and servers to exchange messages in real time with minimal overhead.

This makes WebSockets a strong choice for applications that need low-latency updates, server-initiated messages, or high-frequency data exchange, such as chat systems, collaborative tools, and live dashboards. At the same time, they introduce new considerations around connection management, scaling, and testing that don’t apply to traditional HTTP APIs.

Understanding how WebSockets work under the hood helps you decide when they’re the right tool and how to implement them reliably in production.

Tags:

What do you think about this topic? Tell us in a comment below.

Comment

Your email address will not be published. Required fields are marked *


This site uses Akismet to reduce spam. Learn how your comment data is processed.