Robust WebSocket Reconnection Strategies in JavaScript With Exponential Backoff
WebSockets enable real-time communication between clients and servers, but handling connection drops gracefully is critical. In this guide, we’ll build a reconnection strategy using exponential backoff with jitter, ensuring both reliability and server-friendliness.
Why You Need a Reconnection Strategy
Network issues, server restarts, or even browser tab inactivity can cause disconnections. Without a reconnection system, your app can break silently or hammer the server with repeated attempts.
Step 1: Basic WebSocket Wrapper
class ReconnectingWebSocket {
constructor(url) {
this.url = url;
this.ws = null;
this.maxAttempts = 10;
this.attempt = 0;
this.connect();
}
connect() {
this.ws = new WebSocket(this.url);
this.ws.onopen = () => {
console.log('WebSocket connected');
this.attempt = 0;
};
this.ws.onmessage = (msg) => {
console.log('Received:', msg.data);
};
this.ws.onclose = () => {
console.warn('WebSocket closed. Reconnecting...');
this.reconnect();
};
this.ws.onerror = (err) => {
console.error('WebSocket error:', err);
this.ws.close();
};
}
reconnect() {
if (this.attempt >= this.maxAttempts) {
console.error('Max reconnection attempts reached.');
return;
}
const delay = this.getBackoffDelay(this.attempt);
console.log(`Reconnecting in ${delay}ms`);
setTimeout(() => {
this.attempt++;
this.connect();
}, delay);
}
getBackoffDelay(attempt) {
const base = 500; // 0.5 second
const max = 30000; // 30 seconds
const jitter = Math.random() * 1000;
return Math.min(base * 2 ** attempt + jitter, max);
}
send(data) {
if (this.ws.readyState === WebSocket.OPEN) {
this.ws.send(data);
} else {
console.warn('WebSocket not connected');
}
}
}
Step 2: Usage
const socket = new ReconnectingWebSocket('wss://yourserver.com/ws');
setInterval(() => {
socket.send(JSON.stringify({ type: 'ping' }));
}, 5000);
Step 3: Best Practices
- Use exponential backoff with jitter to avoid thundering herd issues.
- Debounce UI actions that rely on socket availability.
- Store queued messages if you need to send during offline periods.
- Consider application-level ping/pong to detect dead sockets early.
Advanced Additions
- Monitor connection health using
setInterval
and timeouts. - Integrate with Redux or a global state to reflect socket status in UI.
- Add authentication token refresh logic on reconnect.
Conclusion
By implementing a solid reconnection strategy with exponential backoff and jitter, your WebSocket-based applications become more resilient and production-ready. These improvements reduce user disruption and protect your backend from overload during outages.
If this post helped you, consider supporting me: buymeacoffee.com/hexshift