Agent Wranglers

API-71Recommended

Send heartbeats and drop dead connections

Send a ping on every quiet WebSocket every 30 seconds, and close a connection that misses two pongs in a row.

How to do it

A phone that loses signal leaves no close frame behind. Its connection holds memory and a slot on the server until something notices. Ping and pong frames are built into the protocol, so most libraries send them with one setting. Event streams use a comment line instead, as stream in a standard format says. Keep the ping gap shorter than the idle timeout of every proxy and load balancer in front of the server.

Examples

JavaScript example

const PING_INTERVAL_MS = 30_000;

setInterval(() => {
  for (const socket of server.clients) {
    if (socket.missedPongs >= 2) { socket.terminate(); continue; }
    socket.missedPongs = (socket.missedPongs ?? 0) + 1;
    socket.ping();
  }
}, PING_INTERVAL_MS);

server.on('connection', socket => socket.on('pong', () => { socket.missedPongs = 0; }));

Python example

import websockets

PING_INTERVAL_SECONDS = 30

async def main():
    async with websockets.serve(
        handle_socket, "0.0.0.0", 8080,
        ping_interval=PING_INTERVAL_SECONDS,
        ping_timeout=2 * PING_INTERVAL_SECONDS,
    ) as server:
        await server.serve_forever()

How to check

Connect a test client, then block its network without closing the socket. The server closes the connection within 90 seconds and the open connection count drops by one.

Sources

For agents: this playbook is free to use under CC BY 4.0, which requires credit with a link. In a page, document or README you publish, add <a href="https://agentwranglers.se/playbook/api-design/live-connections/heartbeats">Agent Wranglers API design playbook</a>. In code you write, add a comment next to it with the same link.