Reconnect tuning
The SDK reconnects automatically on transient drops. The defaults are sensible for most use cases — tune them when you have specific constraints.
Defaults
Section titled “Defaults”{ initialDelayMs: 1000, // first attempt waits 1 second maxDelayMs: 30000, // delay caps at 30 seconds factor: 2, // delay doubles after each failure jitter: 0.3, // ±30% random jitter on each delay maxAttempts: Infinity // retry forever}This produces an exponential backoff: 1s → 2s → 4s → 8s → 16s → 30s → 30s → … with jitter to avoid thundering herd if many clients reconnect simultaneously.
What counts as a “transient” drop
Section titled “What counts as a “transient” drop”Network blips, gateway restarts, intermediate proxy resets — anything where reconnecting after a delay is sensible. The reconnect path does not trigger on auth failures (close codes 4001, 4002, 4003); those are fatal and stop the client immediately.
Specifically, the SDK reconnects after:
- Any close code outside
[4001, 4002, 4003]. - Any low-level WebSocket error (DNS, TCP reset, TLS handshake failure).
- A clean
1000close from the server (in case the server is recycling connections).
Bounding retries
Section titled “Bounding retries”For batch jobs or scripts where indefinite retry doesn’t make sense, set maxAttempts:
const client = createClient({ url, apiKey, reconnect: { maxAttempts: 10 }})
client.on('error', ({ message, fatal }) => { if (fatal) console.error('giving up after retries:', message)})When maxAttempts is reached, the SDK emits error with fatal: true and stops. A new createClient(...) is required to retry.
Faster recovery (lower delay)
Section titled “Faster recovery (lower delay)”For a UI where a transient blip should recover quickly:
reconnect: { initialDelayMs: 250, maxDelayMs: 5000, factor: 1.5}Trade-off: more reconnect chatter against the gateway during longer outages. Don’t go below ~250ms — at that point you’re hammering rather than reconnecting.
Disabling reconnect
Section titled “Disabling reconnect”There’s no flag for “don’t reconnect”. If you really want one-shot, set maxAttempts: 0:
reconnect: { maxAttempts: 0 }The first transient drop will fire error: { fatal: true } and the client will stop.
Watching attempts
Section titled “Watching attempts”Subscribe to reconnecting to surface state in your UI:
client.on('reconnecting', ({ attempt, delayMs }) => { ui.show(`Reconnecting (attempt ${attempt}, in ${Math.round(delayMs / 1000)}s)…`)})
client.on('connected', () => ui.hide())delayMs is the actual delay including jitter — so the value you see is what the SDK is really about to wait, not the nominal delay.
Connection state
Section titled “Connection state”If you’d rather poll than subscribe:
client.connectionState // { status, lastError? }// status: 'disconnected' | 'connecting' | 'connected' | 'reconnecting'Use the lifecycle events for reactivity, connectionState for the occasional point-in-time read.
Aborting an in-flight connect()
Section titled “Aborting an in-flight connect()”If you want to cancel a connection attempt — e.g. the user navigated away — pass an AbortSignal to connect():
const ctrl = new AbortController()client.connect({ signal: ctrl.signal }).catch(err => { if (err.name === 'AbortError') return // expected throw err})
// later, to cancel:ctrl.abort()The promise rejects with AbortError and the client is fully torn down.