Working with Ping and Pong Frames
1. Understanding Ping/Pong Mechanism
| Frame | Opcode | Purpose |
|---|---|---|
| Ping | 0x9 | Liveness probe |
| Pong | 0xA | Auto/explicit response |
| Payload | ≤ 125 bytes | Optional correlation token |
Warning: The browser
WebSocket API cannot send/observe ping/pong frames — they're auto-handled. Use server-initiated ping or application-level heartbeat.2. Sending Ping Frames
Example: Node ws server ping
import { WebSocketServer } from "ws";
const wss = new WebSocketServer({ port: 8080 });
setInterval(() => {
for (const c of wss.clients) {
if (c.isAlive === false) return c.terminate();
c.isAlive = false;
c.ping();
}
}, 30000);
| Method | Detail |
|---|---|
ws.ping(data, mask, cb) | Send ping |
ws.pong(data) | Explicit pong |
| Auto-pong | ws library responds automatically |
3. Handling Pong Responses
Example: Mark alive on pong
wss.on("connection", (c) => {
c.isAlive = true;
c.on("pong", () => { c.isAlive = true; });
});
| Event | Use |
|---|---|
"pong" | Mark client alive |
"ping" | Optional logging |
4. Implementing Heartbeat
Example: App-level heartbeat (browser)
let hb;
ws.addEventListener("open", () => {
hb = setInterval(() => ws.send(JSON.stringify({ "type": "ping" })), 25000);
});
ws.addEventListener("close", () => clearInterval(hb));
| Interval | Use Case |
|---|---|
| 5-15s | Aggressive (mobile, NAT) |
| 25-30s | Standard |
| 55s | Just under LB idle timeout (60s) |
5. Detecting Stale Connections
| Signal | Threshold |
|---|---|
| No pong in 2 intervals | Mark dead |
| No traffic 60s | Probe |
bufferedAmount stuck | Slow / dead |
6. Closing Dead Connections
| Method | Effect |
|---|---|
close(code,reason) | Sends close frame |
terminate() (ws) | Immediate TCP teardown |
7. Customizing Ping Interval
| Factor | Tune For |
|---|---|
| LB idle timeout | Ping ≤ 80% of timeout |
| Mobile battery | Longer intervals when hidden |
| Latency-critical | Shorter for fast dead-detect |
8. Handling Client Ping
| Source | Behavior |
|---|---|
| Browser | Cannot send protocol pings |
| Node client | ws.ping() supported |
| Server | Auto-pongs any client ping |
9. Monitoring Connection Health
| Metric | Use |
|---|---|
| Heartbeat RTT | Latency trend |
| Missed pongs | Disconnect predictor |
| Reconnect rate | Network quality |
| Buffered bytes | Backpressure |
10. Implementing Custom Heartbeat Protocol
Example: Ping with RTT
const sent = new Map();
function ping() {
const id = crypto.randomUUID();
sent.set(id, performance.now());
ws.send(JSON.stringify({ "type": "ping", "id": id }));
}
function onPong({ id }) {
const rtt = performance.now() - sent.get(id);
sent.delete(id);
metrics.observe("rtt_ms", rtt);
}
| Field | Use |
|---|---|
id | Match ping↔pong |
ts | One-way delay estimate |
seq | Detect missed |