DEV Community

Cover image for What actually breaks in 24/7 WebSocket bots (and how to handle it)
turboline-ai
turboline-ai

Posted on

What actually breaks in 24/7 WebSocket bots (and how to handle it)

What Actually Breaks When You Run a WebSocket Bot 24/7

Running a WebSocket connection for five minutes in a Jupyter notebook is easy. Keeping one alive for 72 hours straight while it makes decisions on live market data is a different animal entirely. The gap between those two things is where most trading bots quietly die.

Here's the stuff that tends to go wrong, and how engineers usually work around it.

The Connection Doesn't Stay Open Forever

WebSockets are persistent, but "persistent" doesn't mean permanent. Brokers, exchanges, and data providers all have their own keepalive rules. Some will silently drop your connection after 30 minutes of low activity. Some will send a ping frame and close you out if you don't pong back within a few seconds. Some give you zero warning.

The fix isn't complicated, but it has to be deliberate. You need a heartbeat loop running independently of your message handler, and you need to treat a missed pong as a hard reconnect trigger, not a warning.

async def heartbeat(ws, interval=20):
    while True:
        await asyncio.sleep(interval)
        await ws.ping()
Enter fullscreen mode Exit fullscreen mode

That's the skeleton. The real work is wiring reconnect logic that doesn't drop buffered state when it fires.

Reconnects Are Where You Lose Data

When a drop happens and you reconnect, there's a window, sometimes a few seconds, sometimes longer, where events have occurred on the exchange side but haven't arrived at your client. If your bot is tracking order book state, that gap corrupts your view of the market.

The reliable pattern here is to treat every reconnect as a full state reset: re-subscribe to all channels, pull a REST snapshot to re-anchor your state, then resume applying the stream deltas on top of that snapshot. It's slower to recover, but it means you're never working from a stale or partial view.

Your Event Loop and Your I/O Can Block Each Other

Python's asyncio makes it easy to write WebSocket handlers that look concurrent but aren't. If your message callback does anything CPU-heavy (signal calculation, model inference, even complex dict comprehensions over a large order book), it can starve the event loop long enough to miss the next incoming frame or delay a heartbeat.

The pattern that works: keep the message handler as thin as possible. Parse the incoming payload, stick it on an asyncio.Queue, and let a separate consumer coroutine do the heavier work. This keeps the I/O path unblocked regardless of what the processing side is doing.

Timestamps Are Lying to You (A Little)

Exchange-side timestamps and your local receive timestamps diverge, and that divergence isn't constant. Network jitter, exchange clock drift, and serialization delays all pile up. If your strategy depends on time ordering across multiple feeds (say, you're correlating two instruments), you can't assume that message A arriving before message B means A actually happened first.

Handling this properly means carrying the exchange timestamp through your entire processing pipeline and using that for any time-sensitive logic, not time.time() on receive.

Volume Spikes Are a Stress Test You Didn't Schedule

Market open, major news events, liquidation cascades: these produce message bursts that can overwhelm a consumer that's sized for average load. A queue that's usually a few items deep suddenly has thousands, and now your bot is processing stale data while the market has already moved.

You need backpressure handling. Either cap your queue and drop old entries when it fills (accepting that you'll miss some events), or design your strategy logic to detect when it's running behind and pause acting until it catches up. The worst outcome is processing a 10-second-old signal and treating it as current.

The Practical Takeaway

Most "24/7 WebSocket bot" tutorials get you to a working connection. The gap is everything that keeps it working: reconnect-safe state management, heartbeat hygiene, async discipline in the message path, and honest handling of time and volume. Getting those right is the actual engineering problem. The WebSocket part is almost the easy bit.

Top comments (0)