Heartbeats and Keep-Alives
Learn to use ping/pong frames and application-level heartbeats to maintain connection liveness and detect dead peers.
Heartbeats and Keep-Alives is a free WebSockets & Realtime Systems Programming lesson on CoddyKit — lesson 3 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the WebSockets & Realtime Systems Programming learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
Why Heartbeats Matter
In realtime applications, maintaining an active and healthy connection is crucial. But what happens if a connection silently drops?
- Heartbeats are small, periodic messages exchanged between connected parties.
- They act as a 'pulse check' to confirm that both the client and server are still alive and responsive.
- This helps detect 'dead' connections that haven't properly closed, preventing resources from being tied up indefinitely.
The Silent Dead Peer
Imagine a client suddenly losing network connectivity (e.g., Wi-Fi drops, device sleeps) without gracefully closing its WebSocket connection.
- The server might still think the client is connected.
- Messages sent to this 'dead' client will never arrive.
- This wastes server resources and leads to inconsistent application states.
- Heartbeats provide a way to proactively identify and terminate these unresponsive connections.
Native WebSocket Pings
The WebSocket protocol includes built-in mechanisms for heartbeats: Ping and Pong frames.
- A server (or client) can send a special
Pingframe to its peer. - Upon receiving a
Ping, the peer is expected to automatically respond with aPongframe. - These frames are lightweight control messages, not application data.
- They confirm the underlying TCP connection is still active and can transmit data.
Server Sends Ping (Node.js)
Here's how a Node.js WebSocket server can send periodic ping frames to its connected clients. The ws library handles the low-level details.
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });
wss.on('connection', ws => {
console.log('Client connected');
// Send a ping every 5 seconds
const pingInterval = setInterval(() => {
if (ws.readyState === WebSocket.OPEN) {
ws.ping();
console.log('Server sent ping.');
}
}, 5000);
ws.on('pong', () => {
console.log('Client responded with pong!');
});
ws.on('close', () => {
console.log('Client disconnected');
clearInterval(pingInterval);
});
ws.on('error', error => {
console.error('WS error:', error);
clearInterval(pingInterval);
});
});
console.log('Server running on ws://localhost:8080');Client Pongs Automatically
When a WebSocket client (like a browser or Node.js client using ws) receives a native Ping frame:
- It automatically sends back a
Pongframe without any explicit code from you. - This makes native pings very efficient for basic connection liveness checks.
- If a
Pingis sent and noPongis received within a timeout, the server can infer the connection is dead and close it.
Beyond Native Pings
While native Ping/Pong frames are great for TCP connection liveness, they have limitations:
- They don't check if the application layer is still responsive.
- Proxies or load balancers might sometimes interfere with or not forward these control frames correctly.
- They don't provide a way to carry custom data, like a timestamp or a user ID.
This is where application-level heartbeats come in.
App Heartbeat Scenarios
Application-level heartbeats are custom messages sent over the WebSocket connection, designed to be handled by your application logic. They are useful for:
- Detecting liveness through WebSocket-unaware proxies.
- Ensuring the application itself (not just the TCP connection) is responsive.
- Implementing more sophisticated timeouts based on user activity, not just network activity.
- Allowing custom data payloads (e.g., client status, last active time).
Client App Heartbeat (Node.js)
A client can send custom 'heartbeat' messages at regular intervals. This example uses a Node.js client, but browser clients would follow a similar pattern.
const WebSocket = require('ws');
const ws = new WebSocket('ws://localhost:8080');
let appHeartbeatInterval;
ws.onopen = () => {
console.log('Connected to server.');
// Send a custom heartbeat every 3 seconds
appHeartbeatInterval = setInterval(() => {
const message = JSON.stringify({
type: 'APP_HEARTBEAT',
timestamp: Date.now()
});
ws.send(message);
console.log('Client sent APP_HEARTBEAT.');
}, 3000);
};
ws.onmessage = event => {
console.log('Received:', event.data);
};
ws.onclose = () => {
console.log('Disconnected.');
clearInterval(appHeartbeatInterval);
};
ws.onerror = error => {
console.error('WS error:', error);
clearInterval(appHeartbeatInterval);
};Server Tracks App Heartbeats
The server receives these custom messages and updates a 'last seen' timestamp for each client. If a client's timestamp isn't updated for too long, the server can close the connection.
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });
wss.on('connection', ws => {
console.log('Client connected');
ws.lastAppHeartbeat = Date.now(); // Initialize timestamp
const checkInterval = setInterval(() => {
// If no app heartbeat in 6 seconds, assume dead
if (Date.now() - ws.lastAppHeartbeat > 6000) {
console.log('Client unresponsive (app heartbeat). Terminating.');
ws.terminate(); // Force close the connection
clearInterval(checkInterval);
}
}, 2000); // Check every 2 seconds
ws.on('message', message => {
const parsed = JSON.parse(message);
if (parsed.type === 'APP_HEARTBEAT') {
ws.lastAppHeartbeat = Date.now(); // Update timestamp
// console.log('Received custom APP_HEARTBEAT from client');
}
// Handle other messages...
});
ws.on('close', () => {
console.log('Client disconnected');
clearInterval(checkInterval);
});
ws.on('error', error => {
console.error('WS error:', error);
clearInterval(checkInterval);
});
});
console.log('Server running on ws://localhost:8080');Check Your Understanding
Select all statements that accurately describe WebSocket heartbeats and keep-alives:
Lesson Summary
We've explored the critical role of heartbeats in maintaining robust WebSocket connections:
- Native Ping/Pong frames check TCP connection liveness, with clients responding automatically.
- Application-level heartbeats provide a more robust and customizable way to ensure the application itself is responsive, especially useful with proxies.
- Both methods prevent 'dead' connections from consuming resources and improve overall system resilience.
Mastering heartbeats is essential for building stable and scalable realtime applications.
Frequently asked questions
Is the “Heartbeats and Keep-Alives” lesson free?
Yes — the full text of “Heartbeats and Keep-Alives” is free to read here on the web, and the WebSockets & Realtime Systems Programming course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the WebSockets & Realtime Systems Programming course, upgrade to CoddyKit PRO.
What will I learn in “Heartbeats and Keep-Alives”?
Learn to use ping/pong frames and application-level heartbeats to maintain connection liveness and detect dead peers. You practise WebSockets & Realtime Systems Programming with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start WebSockets & Realtime Systems Programming?
No prior experience is required. WebSockets & Realtime Systems Programming on CoddyKit is structured for beginners through advanced learners; this is — lesson 3 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Heartbeats and Keep-Alives” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this WebSockets & Realtime Systems Programming lesson?
Yes. Every WebSockets & Realtime Systems Programming lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.