Urgent.News

What's breaking now, across thousands of outlets.

Tech

WebSocket Engineering — Part 2

WebSocket connection :- Heartbeats, Zombie Connections, and the Connections That Never Said Goodbye In Part 1, I reached one uncomfortable conclusion: WebSocket disconnecting is normal. Reliable recovery is the feature. But that created another question. How do I even know that a WebSocket connection has died? At first this sounded obvious. Surely if the client disappears, the server gets a…

Part 2: Understanding WebSocket Disconnections and Heartbeats

In Part 1, I concluded that WebSocket disconnecting is normal. Recovery is the key feature. However, this led to another question: how can I know when a WebSocket connection has died? At first, it seemed obvious that the server would receive a disconnect event if the client vanished. Similarly, TCP and WebSocket should be aware of this. But then I learned about a type of connection failure that doesn't announce itself. The connection simply disappears without a clean goodbye.

Imagine a user connected over Wi-Fi. Then they walk into a lift, and Wi-Fi disappears instantly. Initially, I thought that when Wi-Fi died, WebSocket would send a close event, and the server could clean up the connection. But this isn't always the case. Sometimes, there's no clean TCP close handshake; packets simply stop arriving.

The client is gone, but the server might still have its data, such as subscriptions, presence, and file descriptors. The server thinks the client is connected, but in reality, the client has disappeared. This is a zombie connection.

Initially, I believed heartbeats were simply sending messages every few seconds to prevent WebSocket from disconnecting. But heartbeats serve two purposes: checking if the other side is alive and preventing intermediate proxies from considering the connection idle. There are at least three layers involved in keep-alive: application, WebSocket protocol, and TCP. Each layer has its own idea of keep-alive.

The easiest way to understand this is to think of three layers: application heartbeat, WebSocket ping/pong protocol frames, and TCP keepalive. At first, they all seemed like: "ping something and check if it responds." However, the layer matters a lot. The application-level heartbeat allows us to send a custom message, like `{ type: "ping" }`, which the server can respond to with `{ type: "pong" }`. This heartbeat can be visible to our JavaScript code, allowing us to make decisions based on the connection status.

However, there's a gap in browser JavaScript. The browser doesn't expose protocol ping/pong frames, and we can't directly send ping frames from JavaScript. Instead, we need to create our own heartbeat using application messages. While this may be slightly more expensive due to the extra bytes sent, it allows us to have visibility into the connection status and make appropriate decisions in our application.

Written by urgent.news from Dev.to's reporting — not their text. Machine-written — may contain errors; check the original before relying on it.

Read the original at dev.to →

More in Tech

More from Wednesday 2 September →