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 stuckSlow / dead
6. Closing Dead Connections
Example: Forced terminate
if (c.isAlive === false ) c. terminate (); // skip close handshake
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
idMatch ping↔pong
tsOne-way delay estimate
seqDetect missed