Reconnect Handling
Reconnect is explicit by default. Match sessions can also own retry and heartbeat recovery through autoReconnect, which detects both ordinary socket closes and zombie sockets that still report themselves as open.
Automatic reconnect and heartbeat
const matchSession = simulatorClient.session.create(hostAccess, {
autoReconnect: {
initialDelayMs: 500,
maxDelayMs: 5_000,
maxRetries: 180,
heartbeat: {
intervalMs: 10_000,
timeoutMs: 10_000,
},
},
})With autoReconnect, heartbeat is enabled unless heartbeat: false is set. The session sends a nonce-bearing ping after its socket opens and after each successful pong. If its pong does not arrive before timeoutMs, the SDK closes the stale socket and uses the configured retry backoff. A successful replacement requests an authoritative sync; it does not reconstruct game state from prior events.
The latest snapshot stays available while recovery runs. close() always cancels retries and heartbeat timers.
Basic reconnect
// Reconnect closes the old socket, opens a new one, then syncs state.
await matchSession.reconnect()reconnect():
- Closes the current socket and detaches its listeners.
- Opens a new socket with the same
matchIdandseatToken. - Waits for the normal
welcome+ firstsnapshot. - Sends an explicit
syncRequestso the server resends state.
When to call it:
- The transport dropped (
connectionState === 'closed'unexpectedly). - The app woke from a long background pause.
- The user manually requested a reconnect.
Watch for drops
matchSession.on('connectionState', connectionState => {
if (connectionState === 'closed') {
// Add your own retry/backoff policy when autoReconnect is disabled.
void matchSession.reconnect()
}
})Wrap this with a debounce, retry counter, and exponential backoff if you need to tolerate flapping networks.
Token invalidation
If the server rejects the seat token on reconnect, the handshake fails, reconnect() rejects with an Error, and connectionState becomes closed. In normal operation the token stays valid for the lifetime of the match, so token rejection usually means the match has ended or been evicted. Treat it as a terminal state and re-run the access flow (matches.create() / matches.join()) before trying again.
Preserved state
Across a successful reconnect the SDK keeps the last welcome and the latest snapshot it has seen. Listeners registered with on() are not detached. New snapshot and event values arriving after the reconnect flow through the same subscriptions.
