Reconnect a Live Session

Network disconnect, retry, and resume design.

Recommended design for handling WebSocket disconnects in realtime sessions.

Reconnect decision matrix

Close codeMeaningAction
1000Normal closeDo not reconnect
4408Idle timeoutReconnect immediately
1008Session duration limitReconnect immediately (new session)
1009Frame too largeFix frame size, then reconnect
1011Client socket errorReconnect with backoff
1013Upstream unavailableExponential backoff

Exponential backoff

function reconnectWithBackoff(url, maxRetries = 5) {
  let attempt = 0;
  let lastLanguage = 'zh';

  function connect() {
    const ws = new WebSocket(url);

    ws.onopen = () => {
      console.log('Connected');
      attempt = 0; // reset backoff on success
      // Re-send session configuration
      ws.send(JSON.stringify({ type: 'session.update', language: lastLanguage }));
    };

    ws.onclose = (event) => {
      if (event.code === 1000) return; // normal close

      if (attempt < maxRetries) {
        const delay = Math.min(1000 * Math.pow(2, attempt), 30000);
        attempt++;
        console.log(`Reconnecting in ${delay}ms (attempt ${attempt})`);
        setTimeout(connect, delay);
      }
    };

    ws.onmessage = (event) => {
      // Handle events as normal
    };
  }

  connect();
}

Session continuation

After reconnecting:

  • You get a new session_id — sessions do not resume
  • Re-send session.update to restore language, VAD, and other settings
  • Previous utterances are not re-delivered
  • If you need the complete transcript, accumulate segments client-side

Keep-alive strategies

To avoid idle timeout (4408):

// Send silent frames to keep connection alive
function keepAlive(ws) {
  setInterval(() => {
    if (ws.readyState === WebSocket.OPEN) {
      const silence = new ArrayBuffer(3200); // 100ms of silence
      ws.send(silence);
    }
  }, 5000); // every 5 seconds
}

Session token refresh

Browser connections: session tokens expire in 60 seconds. If reconnection happens after token expiry:

async function connectWithFreshToken() {
  const { token } = await fetch('/session-token', { method: 'POST' }).then(r => r.json());
  return new WebSocket(
    `wss://audio.lansonai.com/v1/audio/transcriptions/stream?access_token=${token}`
  );
}