Tradovate WebSocket Drops: Heartbeats & 24h Limit
A Tradovate socket that keeps disconnecting almost always traces back to three fixable mistakes: missing heartbeats, duplicate request IDs, and holding one connection past the 24-hour limit. Here's each cause and the exact fix.
Stream live ES or NQ quotes into an automated strategy and a Tradovate WebSocket that silently disconnects can leave a position unmanaged for minutes before you even notice. Tradovate's real-time socket is unforgiving. The server closes an idle connection within about 10 seconds if it stops hearing from your client, and a single connection has a hard lifespan measured in hours, not days. When a Tradovate WebSocket keeps disconnecting, it almost always comes down to three fixable mistakes, missing heartbeats, duplicate request IDs, and holding one connection past the 24-hour limit, plus a fourth, flooding the socket with requests. Below, you'll get each cause, the exact fix, and how routing your alerts through PickMyTrade skips the raw socket plumbing altogether.
Quick Checklist for Tradovate WebSocket Drops
- Send a heartbeat every 2.5 seconds, a frame containing an empty array
[], sent from the client, keeps the socket open. - Don't trust setInterval in a browser tab, background tabs throttle timers and starve your heartbeat. Use a timestamp check or a Web Worker.
- Give every request a unique, incrementing i (request ID), never reuse an integer ID on the same socket.
- Pace your requests, bursting too many frames too quickly triggers a server-side disconnect.
- Reconnect before ~24 hours, a single Tradovate WebSocket isn't meant to live indefinitely, so schedule a clean reconnect.
- Renew the access token before it expires, an expired token means your re-authorize on reconnect fails.
What "Tradovate WebSocket Keeps Disconnecting" Means
Tradovate's WebSocket protocol is chatty by design. After you open the socket, the server sends an open frame (o), you send an authorize frame with your access token, and from then on both sides are expected to keep talking. If the server doesn't hear anything from your client for roughly 10 seconds, it assumes the connection is dead and closes it. That's why a socket that “was working a second ago” drops the moment your code stops sending frames.
Here's the catch that surprises most developers: once you subscribe to a live data feed, the server stops sending you its own heartbeat frames because the streaming messages themselves prove the link is alive. Your client, though, still has to prove it is alive. If your data feed goes quiet, a slow overnight session, a thin symbol, and your client isn't sending its own heartbeats, the server closes the socket even though nothing is “wrong.”
On top of the idle timeout, holding a single connection open for more than 24 hours leads to disconnections. So even a perfectly behaved, heartbeat-sending client eventually gets dropped if it never reconnects. Understanding these two clocks, the ~10-second idle timer and the ~24-hour connection ceiling, is the key to a stable feed.
Top Causes of Tradovate WebSocket Drops in 2026
1. No heartbeat (or a late one)
This is the number-one cause. Your client is responsible for sending a heartbeat every 2.5 seconds, a frame whose text is exactly [], to avoid being closed for inactivity. Miss the window and the socket closes.
2. Browser tabs throttling your timer
If your app runs in a browser and you drive heartbeats with setInterval or setTimeout, an inactive or background tab gets its timers throttled by the browser. Your heartbeats arrive late or stop entirely, and the socket dies “for no reason” the moment you switch tabs.
3. Duplicate request IDs
Every request you send carries an integer ID in its i field. Send two requests with the same i on the same socket and you confuse the request/response matching, which can break the connection or leave you waiting forever for a response that never resolves cleanly.
4. Sending requests too rapidly
Fire a burst of frames at the socket, subscribing to dozens of symbols in a tight loop, say, or hammering order modifications, and you can trip Tradovate's flood protection and cause a disconnect.
5. Hitting the 24-hour limit or an expired token
A connection held open past roughly 24 hours gets dropped. Related: the access token behind your session expires (Tradovate access tokens are short-lived, on the order of 90 minutes), so if you try to re-authorize a reconnected socket with a stale token, the auth fails and you stay disconnected.
How to Fix Tradovate WebSocket Drops: Step-by-Step
Fixing Missing Heartbeats
Start a heartbeat routine after authorizing
As soon as your socket is authorized, start a heartbeat routine.
Send the empty array on a 2.5s cadence
Every 2.5 seconds (2500 ms), send a frame containing an empty array [] using the standard WebSocket send method.
Keep sending even while streaming
Keep sending heartbeats even while streaming market data, don't assume the server's silence means the link is healthy. When live data is flowing, the server stops sending its own heartbeats, so yours are the only thing keeping the socket open during quiet stretches.
Treat it as fire-and-forget
Treat the heartbeat as fire-and-forget. It carries no request ID and expects no response.

Fixing Browser-Tab Throttling
Stop relying on setInterval alone
Stop relying on setInterval / setTimeout alone for heartbeats in a browser.
Use a timestamp-based approach
Use a timestamp-based approach instead: on every incoming message, record the current time and compare it to the time of the last heartbeat. If more than 2500 ms have elapsed, send a heartbeat frame immediately.
Move the timer off the main thread
For apps that must survive long stretches with no incoming data in a background tab, move the timer into a Web Worker (which isn't throttled the same way), or run the socket in a server-side Node.js process where there's no inactive-tab concept at all.
Fixing Duplicate Request IDs
Maintain one incrementing counter
Maintain a single, monotonically increasing counter for the i field on each socket.
Reserve the low IDs for setup
Reserve the low IDs the protocol uses for setup (authorization and the initial sync request) and start your general counter above them.
Increment atomically
Increment the counter atomically so two async tasks can never grab the same value. In multi-threaded or heavily concurrent code, guard the counter with a lock, a closure, or a thread-safe structure.
Never reuse an ID on retry
Never hand-write the same ID twice. If you retry a request, give the retry a fresh ID.

Fixing Request Floods and the 24-Hour Limit
Throttle outbound frames
Queue your requests and release them at a steady pace instead of bursting. Spacing subscriptions and order actions keeps you under the socket's tolerance.
Schedule a proactive reconnect
Don't wait for the ~24-hour drop. Reconnect on your own schedule (well inside 24 hours), re-send the authorize frame, and re-subscribe to your feeds so the switch is smooth.
Refresh the token first
Track your access token's expiry and renew it before it lapses so the re-authorize on reconnect always uses a valid token. Exact token lifetimes are set by Tradovate and can change, check the current API docs rather than hard-coding a number.
Auto-recover on every unexpected close
Treat every unexpected close as an error and auto-recover. Unless you're intentionally shutting down, reopen the socket, re-authorize, and resubscribe automatically. Add a timeout on pending responses so a stuck request never hangs your whole client.

Troubleshooting Table
| Symptom / error | What it means | Fix |
|---|---|---|
| Socket closes after ~10 seconds of silence | No client heartbeat; server closed the idle connection | Send an empty-array [] heartbeat every 2.5s |
| Feed dies the moment the tab goes to background | Browser throttled setInterval / setTimeout | Use timestamp-based heartbeats or a Web Worker |
| Live data stops but socket "looks" connected | Server stopped its own heartbeats while streaming; client sent none | Keep sending client heartbeats even while streaming |
| Responses mismatch or requests hang | Duplicate integer i (request ID) values | Use one atomic, incrementing request-ID counter |
| Connection drops after a burst of frames | Too many requests sent too rapidly | Queue and pace outbound requests |
| Connection drops around the 24-hour mark | Single connection held past its lifespan | Reconnect, re-authorize, and resubscribe well inside 24h |
| Re-authorize fails after a reconnect | Access token expired | Renew the token before it expires, then re-send authorize |
Prevent This with PickMyTrade
If you're wiring up automation just to get orders into Tradovate, you may not need to manage a raw WebSocket at all. PickMyTrade takes your TradingView alerts and delivers them to Tradovate for you, so the heartbeat timing, request-ID hygiene, and reconnect logic all live on our side:
- Managed Connection Health, the connection to Tradovate is kept alive and reconnected for you, so heartbeat gaps and the 24-hour ceiling never reach your strategy.
- Rate-Limit-Safe Routing, alerts are paced and queued so a burst of signals never floods the socket into a disconnect.
- Token & Session Handling, authentication and renewal are managed behind the scenes, so an expired token never silently kills your automation.
- Multi-Account Sync, one alert mirrors cleanly across multiple Tradovate accounts without you juggling a socket per account.
Trade Rejection-Free
Start your free 5-day trial, link your alerts today and trade rejection-free.
Start Your Free 5-Day TrialFrequently Asked Questions
Every 2.5 seconds. The client sends a frame containing an empty array []. If the server hears nothing from your client for roughly 10 seconds, it closes the socket for inactivity.
It is simply the text [], an empty JSON array, sent with the standard WebSocket send method. It has no request ID and expects no response.
Browsers throttle setInterval and setTimeout in background tabs, so timer-driven heartbeats arrive late and the socket times out. Use a timestamp check on incoming messages, or move the timer into a Web Worker, so heartbeats keep firing when the tab is inactive.
Yes. Once you subscribe to a data feed, the server stops sending its own heartbeats because the streaming messages prove the link is alive, but your client must still prove it is alive. During quiet stretches with no incoming data, your heartbeats are the only thing keeping the socket open.
Each request carries an integer i, and responses are matched back to that ID. Reusing an ID on the same socket confuses that matching and can hang requests or drop the connection. Use a single atomic counter that increments for every request.
Yes. Holding one connection open beyond about 24 hours leads to disconnection. The reliable pattern is to reconnect on your own schedule, well inside 24 hours, then re-authorize and resubscribe, rather than expecting a single socket to live forever.
Your access token likely expired. Tradovate access tokens are short-lived, so renew the token before it lapses and re-send the authorize frame with a valid token on every reconnect. Exact token lifetimes are set by Tradovate and can change, so confirm them in the current API docs.
If your goal is simply to automate Tradovate orders from TradingView, use a bridge like PickMyTrade so the connection health, pacing, and token handling are managed for you instead of maintaining a raw socket yourself.
This guide is for educational and informational purposes only and is not financial, investment, or trading advice. Trading futures and other leveraged products carries a substantial risk of loss and is not suitable for every investor. PickMyTrade is an independent third-party automation platform and is not affiliated with, endorsed by, or sponsored by Tradovate, Inc. "Tradovate" and all related names, logos, and trademarks are the property of their respective owners. Platform features and steps change over time, so always confirm the current process in the official Tradovate platform and documentation before acting.