Skip to content

WebSocket Reconnection Strategies — Complete Guide

DodaTech Updated 2026-06-28 3 min read

In this tutorial, you will learn about Websocket Reconnection Strategies. We cover key concepts, practical examples, and best practices to help you master this topic.

WebSocket connections can drop due to network issues, server restarts, or client mobility. Reconnection strategies automatically restore connections with minimal data loss. Exponential backoff prevents server overload during mass reconnection events.

What You'll Learn

  • Exponential backoff reconnection algorithm
  • Connection state management
  • Event buffering during disconnection
  • Idempotent reconnection patterns
  • Socket.IO built-in reconnection

Why It Matters

Every production WebSocket application must handle disconnection gracefully. Without reconnection, users lose real-time features until they manually refresh. Poor reconnection logic can overwhelm servers after an outage.

Real-World Use

Slack reconnects with exponential backoff and replays missed events. Discord uses resume tokens to restore state after reconnection. Trading platforms buffer events during short disconnections.

flowchart TD
    Connected[Connected] -->|Disconnect| Wait[Wait: initialDelay]
    Wait -->|Retry| Attempt[Attempt Connection]
    Attempt -->|Success| Connected
    Attempt -->|Fail| Increase[Double Delay]
    Increase -->|Delay < Max| Wait
    Increase -->|Delay >= Max| MaxWait[Stay at Max Delay]
    MaxWait --> Attempt

Teacher Mindset

Assume connections will drop. Plan for it. Use exponential backoff with jitter to avoid thundering herd. Buffer events during disconnection and replay them on reconnect.

Code Examples

// Example 1: Custom reconnection with exponential backoff
class ReconnectingSocket {
  constructor(url, options = {}) {
    this.url = url;
    this.maxRetries = options.maxRetries || Infinity;
    this.initialDelay = options.initialDelay || 1000;
    this.maxDelay = options.maxDelay || 30000;
    this.delay = this.initialDelay;
    this.retries = 0;
    this.connect();
  }

  connect() {
    this.ws = new WebSocket(this.url);

    this.ws.onopen = () => {
      this.delay = this.initialDelay;
      this.retries = 0;
      console.log('Connected');
    };

    this.ws.onclose = () => {
      if (this.retries < this.maxRetries) {
        const jitter = Math.random() * 1000;
        setTimeout(() => {
          this.retries++;
          this.delay = Math.min(this.delay * 2, this.maxDelay);
          this.connect();
        }, this.delay + jitter);
      }
    };

    this.ws.onerror = () => this.ws.close();
  }

  send(data) {
    if (this.ws?.readyState === WebSocket.OPEN) {
      this.ws.send(data);
    } else {
      console.warn('Cannot send, not connected');
    }
  }
}
// Example 2: Socket.IO built-in reconnection
const socket = io('http://localhost:3000', {
  reconnection: true,
  reconnectionAttempts: 10,
  reconnectionDelay: 1000,
  reconnectionDelayMax: 30000,
  randomizationFactor: 0.5
});

socket.on('connect', () => {
  console.log('Connected');
  // Re-subscribe after reconnect
  socket.emit('subscribe', { room: 'general' });
});

socket.on('reconnect_attempt', (attempt) => {
  console.log(`Reconnection attempt ${attempt}`);
});

socket.on('reconnect_error', (error) => {
  console.error('Reconnection error:', error.message);
});

socket.on('reconnect_failed', () => {
  console.error('Failed to reconnect after all attempts');
});
// Example 3: Event buffering during disconnect
class BufferedSocket {
  constructor(url) {
    this.buffer = [];
    this.connected = false;
    this.connect(url);
  }

  connect(url) {
    this.ws = new WebSocket(url);

    this.ws.onopen = () => {
      this.connected = true;
      // Flush buffered events
      while (this.buffer.length > 0) {
        this.ws.send(this.buffer.shift());
      }
    };

    this.ws.onclose = () => {
      this.connected = false;
    };
  }

  send(data) {
    if (this.connected) {
      this.ws.send(data);
    } else {
      this.buffer.push(data);
    }
  }
}

Common Mistakes

  • Reconnecting immediately without delay, causing connection storms
  • Not using jitter in the backoff algorithm
  • Forgetting to re-subscribe to rooms after reconnection
  • Not limiting the number of reconnection attempts
  • Buffering events without a size limit, causing memory growth

Practice

  1. Implement exponential backoff with jitter for WebSocket reconnection.
  2. Add reconnection attempt counting and max retries.
  3. Implement event buffering with a max buffer size.
  4. Re-subscribe to rooms after successful reconnection.
  5. Challenge: Build a reconnection system with a state machine (CONNECTED, RECONNECTING, CLOSED, BUFFERING).

FAQ

What is the best initial reconnection delay?

1000-2000ms is typical. Shorter for user-facing apps, longer for background connections.

How does Socket.IO reconnection work internally?

Socket.IO reconnects using the same transport negotiation as the initial connection. It supports reconnection with session recovery.

Should I buffer events during disconnection?

Yes, but limit the buffer size and age. Discard old events when the buffer is full.

What is the thundering herd problem in reconnection?

When many clients disconnect simultaneously (server restart) and all reconnect at the same time, overwhelming the server.

How do I prevent duplicate events after reconnection?

Use idempotent operations on the server. The client should track event IDs and the server should deduplicate.

Mini Project

Build a reconnecting WebSocket client with exponential backoff (1s initial, 30s max), jitter, event buffering (max 100 events), and automatic room re-subscription. Test by restarting the server.

What's Next

Next, you will learn about WebSocket heartbeats for connection health monitoring.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro