Skip to main content
The client keeps the connection healthy and recovers from drops on its own. In the normal case you never write reconnect logic — you subscribe once, and your subscriptions survive across disconnects. This page covers what happens underneath so you know when to intervene.

Keepalive

The client runs an application-level ping/pong on the open socket. If pongs stop coming back it treats the connection as dead and tears it down, which kicks off a reconnect. A single dropped pong is tolerated, so a brief network blip doesn’t cause a needless reconnect. This is layered on top of the server’s own connection-level keepalive — see Connection lifecycle.

Reconnect with resubscribe

When the socket closes unexpectedly, the client reconnects with exponential backoff and jitter, emitting a reconnecting event before each attempt:
Server-assigned subscriptionIds are scoped to a single connection and don’t survive a reconnect, so the client replays your active subscriptions — the (market, channel) pairs you asked for — on every new connection. You’ll receive a fresh subscribed ack and a new snapshot for each. Because resubscribe is automatic, subscriptions you create before the socket is even open are honored too (they’re sent once the connection is ready). The backoff budget resets only once a connection is confirmed by a welcome frame — so a transient drop after a healthy session gets the full retry budget, while an endpoint that never establishes a session is bounded (see below). Subscriptions the server permanently retires are not replayed: a status frame with state: "closed" or "unsupported", or an error frame rejecting a market at subscription time, prunes that entry so it isn’t retried on reconnect.

goodbye and terminal disconnects

Before closing a connection the server sends a goodbye frame with a reason. The client treats these two ways:
  • Recoverableshutdown, ttl, idleTimeout, and noActiveSubs (when you still have subscriptions to replay). The client reconnects normally.
  • TerminalauthRevoked and kicked (and noActiveSubs when there’s nothing left to resubscribe). Reconnecting with the same key would be futile, so the client stops.
When the client stops for good it emits a terminated event. This also fires if reconnecting repeatedly fails without ever establishing a session (e.g. a bad stream key or an unreachable endpoint), instead of looping forever. terminated is final: that client will not reconnect. A fresh client starts with none of your handlers or subscriptions, so wrap setup in a start function that creates the client, registers handlers, and subscribes — then call it both initially and from the terminated handler to resume:

Closing intentionally

Calling close() yourself is not a disconnect the client recovers from — it closes the socket and stops all reconnect attempts. Use it on shutdown or when you’re done streaming.