> ## Documentation Index
> Fetch the complete documentation index at: https://docs.radion.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Reconnect & heartbeats

> Automatic reconnect, subscription restore, and heartbeat keep-alive.

The realtime client keeps the connection healthy for you. Both reconnect and heartbeat are on by default, and you can tune them in [configuration](/sdks/configuration).

## Reconnect & subscription restore

If the connection drops by surprise, the client reconnects on its own. It waits a bit longer between each try (exponential backoff) and adds a little random delay (jitter). Once the socket is back, it re-sends every active subscription. After you call `close()`, it stops trying.

Each reconnect try fires a `reconnect` lifecycle event with the try number and the wait before the next try.

<CodeGroup>
  ```typescript TypeScript theme={null}
  const radion = new Radion({
    apiKey: process.env.RADION_API_KEY,
    realtime: {
      reconnect: {
        initialDelayMs: 500,
        maxDelayMs: 30_000,
        factor: 2,
        jitter: 0.2,
      },
    },
  });

  radion.realtime.onLifecycle("reconnect", ({ attempt, delayMs }) =>
    console.log(`reconnect #${attempt} in ${delayMs}ms`)
  );

  // disable auto-reconnect entirely:
  // new Radion({ apiKey, realtime: { reconnect: false } });
  ```

  ```python Python theme={null}
  radion = Radion(api_key="sk_...", reconnect=True)

  @radion.realtime.on_lifecycle("reconnect")
  async def reconnecting(info):
      print(info["attempt"], info["delay"])

  # disable auto-reconnect entirely:
  # Radion(api_key="sk_...", reconnect=False)
  ```

  ```rust Rust theme={null}
  use futures_util::StreamExt;
  use radion_sdk::realtime::{LifecycleEvent, ReconnectOptions, RealtimeClient, RealtimeOptions};
  use std::time::Duration;

  let client = RealtimeClient::new(
      RealtimeOptions::new("sk_...").reconnect(ReconnectOptions {
          initial_delay: Duration::from_millis(500),
          max_delay: Duration::from_secs(30),
          factor: 2.0,
          jitter: 0.2,
      }),
  );

  let mut lifecycle = client.lifecycle();
  while let Some(event) = lifecycle.next().await {
      if let LifecycleEvent::Reconnect { attempt, delay } = event {
          println!("reconnect #{attempt} in {delay:?}");
      }
  }

  // disable auto-reconnect entirely:
  // RealtimeOptions::new("sk_...").disable_reconnect();
  ```
</CodeGroup>

## Heartbeats

The client sends a ping every so often. Any incoming frame proves the connection is alive. If nothing arrives before the timeout, the client treats the connection as dead, closes it, and reconnects.

* **TypeScript** — `heartbeat: { intervalMs, timeoutMs }`, or `heartbeat: false` to disable.
* **Python** — `heartbeat=True/False`, `heartbeat_interval`, `heartbeat_timeout` (seconds).
* **Rust** — `RealtimeOptions::heartbeat(HeartbeatOptions { interval, timeout })` (both `Duration`), or `.disable_heartbeat()`.

This is separate from the WebSocket ping/pong the server uses at the protocol level. See [Connection state](/websockets/connection-state) for how that works.
