VIZANIXTrading Software Development
Bybit APIWebSocket10 min read

Bybit WebSocket: heartbeat, disconnects and the state you must not trust

A dropped WebSocket is not an error to log. It is a moment when your bot's picture of the world and reality quietly diverge.

Vizanix engineering · about the author

ARTICLE
10 minreading time
SECTION
Bybit API
PUBLISHED
2026-08-28
CHAPTERS
6
READ NEXT
3
LANGUAGE
written in English
An engineering breakdown, not a rewrite of the docs.
WEBSOCKETHEARTBEATSEQUENCERESUBSCRIBESHARDING

Every WebSocket client eventually reconnects. The question that separates a production bot from a script is what it is allowed to do in the seconds after the socket comes back.

During a disconnect the exchange kept trading. Orders filled. Positions changed. Your bot's in-memory state is now a historical document. A bot that resumes its strategy loop immediately on reconnect is making decisions from that document.

Heartbeat is a liveness check, not a formality

Bybit expects a periodic ping and answers with a pong. The value is not in the protocol niceties — it is that a TCP connection can stay open and completely dead. A firewall drops the flow, the socket never errors, and your bot sits happily waiting for market data that will never arrive.

So the rule is: track the time since the last received message, not since the last error. If nothing has arrived for longer than the interval you expect, the connection is dead regardless of what the socket object claims. Tear it down yourself.

python
# Liveness is measured on inbound traffic, not on the socket's opinion.
last_msg = time.monotonic()

async def watchdog(ws, idle_limit=30.0):
    while True:
        await asyncio.sleep(5)
        if time.monotonic() - last_msg > idle_limit:
            log.warning("no data for %.1fs — forcing reconnect", idle_limit)
            await ws.close()          # let the reconnect path own recovery
            return

Sequence numbers exist so you can detect what you missed

Order book streams are incremental: a snapshot followed by deltas, each carrying a sequence identifier. If the sequence jumps, you missed an update and your local book is wrong. Not slightly wrong — arbitrarily wrong, because a missed delta can be the one that removed the level you are about to quote against.

There is exactly one correct response to a sequence gap: throw away the local book and request a fresh snapshot. Interpolating, ignoring small gaps, or “it will resync eventually” are all ways of trading against a book that does not exist.

Resubscription is not automatic

Reconnecting restores the transport. It does not restore your subscriptions. A reconnect handler that opens the socket and returns leaves you connected to a stream that sends nothing — which the watchdog above will then correctly kill, producing a reconnect loop that looks like a network problem and is not.

Keep the subscription set as explicit state, and treat resubscribe as part of the connect sequence rather than something that happens afterwards. Bybit caps the number of arguments per subscribe request, so a large universe needs batching.

Shard before you need to

One socket carrying a thousand topics is a single point of failure with a long recovery time: when it drops, everything drops, and the resubscribe storm is at its worst exactly when the venue is already under stress.

Our candle pipeline runs ten shards. In steady state that is around 1 850 topics across 725 symbols, feeding 1 450 buffers, sustaining roughly 900 messages per second. When one shard drops, the other nine keep working and the strategy loses a tenth of its universe for a few seconds instead of all of it.

Sharding also makes failure legible. “Shard 7 is down” is an actionable statement. “The WebSocket is flapping” is not.

What the bot must do before it trades again

This is the part most implementations skip. On reconnect, before the strategy loop is allowed to emit a single order:

  1. Re-fetch open orders from REST and reconcile against local state.
  2. Re-fetch positions and compare with what the bot believed it held.
  3. Re-fetch balance — margin may have moved for reasons unrelated to this bot.
  4. Request fresh order book snapshots for every subscribed symbol.
  5. Only then, unblock the strategy.

The reconciliation step will occasionally find something. An order that filled during the gap. A position that a stop closed. A partial fill that changed the average price. Each of those, acted on with stale state, is a real loss — and each is invisible to a bot that trusts its memory.

Reconnects are normal; unnoticed reconnects are not

Over one logged period our executor recovered from 48 automatic reconnects without a single manual intervention. That number is not a boast — reconnects are ordinary. What matters is that each one was recorded, each one triggered reconciliation, and none of them produced a duplicate order.

Count them. A reconnect rate that suddenly triples is telling you something about your network, your host or the venue, and it is telling you before the incident rather than during it. This belongs in the same health output as latency and reject rate — see monitoring a trading bot.

This article describes engineering practice. It is not investment advice. Vizanix develops software and does not promise trading returns.

Blog

Read next

Operations · 7 min

Monitoring a trading bot: everything except P&L

P&L tells you what happened. It does not tell you whether the machine that produced it is working — and by the time P&L reveals a broken bot, it has been broken for a while.

Want this running for you?

We write about what we build. If you need it built, get in touch — scoping is free.

Brief

Get a project estimate

Four questions and your contact. No deposit required to talk — if the job is not a fit, we say so straight away.

01What do you need
02Exchange
03Market
04Strategy
05Contacts

Prefer to write directly? Telegram @vx_ceo

Discuss a system