Tool · Trading Bot Reliability

WebSocket Reconnect Config Generator

Generate production-ready WebSocket reconnect strategies for Binance, Bybit, Kraken, KuCoin, and OKX. Backoff, ping/pong intervals, state recovery, and connection throttling — copy-paste ready in YAML, Python, or C#.

5exchanges
4stream types
3output formats

WebSocket drops are the #1 silent killer of trading bots. Exchange streams disconnect constantly — rate limits, network blips, server restarts. A bad reconnect strategy amplifies the problem: thundering herd reconnects trigger more rate limits, missing state recovery means data gaps, and wrong ping intervals cause the exchange to drop you preemptively. This generator gives you the exact config for your exchange + stream type.

Generator

1 conn/IP per stream type · Ping: 180s

24hr ticker, mini-ticker, book ticker

Delay doubles each attempt: 1s → 2s → 4s → 8s

Stop retrying after this many failures

Total time allowed for all reconnect attempts

Max gap before triggering alert (0 = no gaps allowed)

Connection Summary

Base URL:

wss://stream.binance.com:9443/ws

Strategy:

Exponential Backoff

Delay range:

1s → 150s

State recovery:

Resubscribe

Ping interval:

180s

Reconnect timeout:

2s

Stream limit:

200 / conn

Acceptable gap:

5s

Binance note: Combined streams let you pack up to 200 symbols into one connection. Use /stream?streams= for multi-symbol subscriptions.

Connection strategy: Up to 200 streams per connection — batch subscriptions

# Binance WebSocket Reconnect Config
# Generated by MatrixTrak WebSocket Reconnect Config Generator
# Stream: Ticker / Price | Backoff: Exponential Backoff

websocket:
  exchange: binance
  base_url: "wss://stream.binance.com:9443/ws"
  stream_type: ticker

reconnect:
  strategy: exponential
  max_attempts: 10
  max_window_sec: 300
  initial_delay_sec: 1
  max_delay_sec: 150
  reconnect_timeout_sec: 2
  acceptable_gap_sec: 5

keepalive:
  ping_interval_sec: 180
  pong_timeout_sec: 270

connection:
  max_streams_per_conn: 200
  limit: "1 conn/IP per stream type"
  note: "Combined streams let you pack up to 200 symbols into one connection. Use /stream?streams= for multi-symbol subscriptions."

state_recovery:
  needs_snapshot: false
  strategy: "Resubscribe and accept gap (ticker/trade is stateless)"

recommendations:
  - Up to 200 streams per connection — batch subscriptions
  - Monitor close codes — 1006 = abnormal, 1008 = policy violation
  - Log every reconnect attempt with attempt number and delay
  - Alert if reconnect attempts exceed 50% of max_attempts
import asyncio
import websockets
import json
import random

WS_URL = "wss://stream.binance.com:9443/ws"
MAX_ATTEMPTS = 10
MAX_WINDOW = 300
PING_INTERVAL = 180
ACCEPTABLE_GAP = 5
RECONNECT_TIMEOUT = 2
INITIAL_DELAY = 1
MAX_DELAY = 150

async def connect_with_reconnect():
    attempt = 0
    delay = INITIAL_DELAY
    start_time = asyncio.get_event_loop().time()

    while attempt < MAX_ATTEMPTS:
        try:
            async with websockets.connect(
                WS_URL,
                ping_interval=PING_INTERVAL,
                ping_timeout=PING_INTERVAL * 1.5,
                close_timeout=RECONNECT_TIMEOUT,
            ) as ws:
                # Reset delay on successful connection
                delay = INITIAL_DELAY
                attempt = 0
                print(f"Connected to Binance ({streamType})")

                async for message in ws:
                    # Process message
                    data = json.loads(message)
                    yield data

        except (websockets.ConnectionClosed, OSError) as e:
            attempt += 1
            elapsed = asyncio.get_event_loop().time() - start_time
            if elapsed > MAX_WINDOW:
                raise Exception(f"Reconnect window exceeded: {MAX_WINDOW}s")

            print(f"Disconnected (attempt {attempt}/{MAX_ATTEMPTS}). "
                  f"Reconnecting in {delay:.1f}s... (close code: {getattr(e, 'code', 'N/A')})")

            await asyncio.sleep(delay)
            delay = min(delay * 2, 150)

    raise Exception(f"Max reconnect attempts ({MAX_ATTEMPTS}) exhausted")

# Usage
async def main():
    async for data in connect_with_reconnect():
        print(f"Received: {json.dumps(data)[:200]}")
using System.Net.WebSockets;
using System.Text;

const string WsUrl = "wss://stream.binance.com:9443/ws";
const int MaxAttempts = 10;
const int MaxWindowSec = 300;
const int PingIntervalSec = 180;
const int AcceptableGapSec = 5;
const int ReconnectTimeoutSec = 2;
const double InitialDelaySec = 1;
const double MaxDelaySec = 150;

async IAsyncEnumerable<string> ConnectWithReconnect(
    [EnumeratorCancellation] CancellationToken cancel = default)
{
    var attempt = 0;
    var delay = InitialDelaySec;
    var windowStart = DateTime.UtcNow;

    while (attempt < MaxAttempts)
    {
        using var ws = new ClientWebSocket();
        ws.Options.KeepAliveInterval = TimeSpan.FromSeconds(PingIntervalSec);
        ws.Options.AddSubProtocol("json");

        try
        {
            await ws.ConnectAsync(new Uri(WsUrl), cancel);

            // Reset on successful connection
            delay = InitialDelaySec;
            attempt = 0;
            Console.WriteLine($"Connected to Binance ({streamType})");

            var buffer = new byte[8192];
            while (ws.State == WebSocketState.Open)
            {
                var result = await ws.ReceiveAsync(buffer, cancel);
                if (result.MessageType == WebSocketMessageType.Close)
                    throw new WebSocketException("Server closed connection");

                var text = Encoding.UTF8.GetString(buffer, 0, result.Count);
                yield return text;
            }
        }
        catch (Exception ex) when (ex is not OperationCanceledException)
        {
            attempt++;
            var elapsed = (DateTime.UtcNow - windowStart).TotalSeconds;
            if (elapsed > MaxWindowSec)
                throw new InvalidOperationException(
                    $"Reconnect window exceeded: {MaxWindowSec}s");

            var closeStatus = (ws.CloseStatus != null)
                ? $" (code: {(int)ws.CloseStatus})"
                : "";
            Console.WriteLine(
                $"Disconnected (attempt {attempt}/{MaxAttempts}). " +
                $"Reconnecting in {delay:F1}s...{closeStatus}");

            await Task.Delay(TimeSpan.FromSeconds(delay), cancel);
            delay = Math.Min(delay * 2, MaxDelaySec);
        }
    }

    throw new InvalidOperationException(
        $"Max reconnect attempts ({MaxAttempts}) exhausted");
}

Related tools

Frequently asked questions

Frequently asked questions

Why does my WebSocket keep disconnecting from Binance?
The most common causes: (1) You're not sending pings every 3 minutes — Binance drops silent connections. (2) You've opened too many connections from the same IP — Binance enforces 1 connection per stream type per IP. (3) You're hitting rate limits on REST endpoints while the WS is open, which can trigger IP-level throttling. Use combined streams to reduce connection count.
What's the best backoff strategy for exchange WebSockets?
Decorrelated jitter is the safest choice — it prevents all your reconnect attempts from landing at the same time (thundering herd). For Binance: exponential backoff with jitter, 1s → 2s → 4s → 8s, max 5 min. For Kraken: fixed 5s with jitter is sufficient. Avoid pure exponential without jitter — it creates synchronized retry waves across all your connections.
How do I recover state after a WebSocket disconnect?
For order book streams: fetch a REST snapshot immediately on reconnect, then replay all WS delta updates with updateId > snapshot lastUpdateId. For user data streams: refetch account/position state via REST after reconnect — never trust partial WS state. For ticker/trade streams: simply resubscribe; the gap is acceptable since ticker data is continuous.
What does WebSocket close code 1006 mean?
1006 = Abnormal Closure. The connection dropped without a proper close handshake. Common causes: network interruption, server restart, or the exchange killing the connection due to rate limiting. Treat 1006 as a transient failure — reconnect with backoff. If 1006 repeats every few seconds, check your connection count and ping interval.
Should I use one WebSocket connection or multiple?
Depends on the exchange. Binance supports 200 combined streams per connection — use one connection for all your ticker/orderbook needs. Bybit and OKX require separate connections per channel. Kraken supports unlimited subscriptions on one connection. Fewer connections = fewer failure points and less reconnect churn.

What engineers say

What engineers say

The retry policy generator alone saved us from a production incident. We had exponential backoff configured wrong for months — the timeline visualization made it obvious instantly.
A

Alex R.

Senior Backend Engineer, Fintech Startup

1 / 16

Newsletter

Weekly engineering insights

Get practical tips on AI, .NET, trading bot reliability, and building scalable systems. No spam, unsubscribe anytime.