Tradovate API

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.

Geprüft vom PickMyTrade Trading Systems Team Zuletzt aktualisiert
· 8 min read
Browser DevTools Network tab showing Tradovate WebSocket frames and a dropped connection

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

1

Start a heartbeat routine after authorizing

As soon as your socket is authorized, start a heartbeat routine.

2

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.

3

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.

4

Treat it as fire-and-forget

Treat the heartbeat as fire-and-forget. It carries no request ID and expects no response.

Tradovate WebSocket client sending an empty-array heartbeat frame every 2.5 seconds

Fixing Browser-Tab Throttling

1

Stop relying on setInterval alone

Stop relying on setInterval / setTimeout alone for heartbeats in a browser.

2

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.

3

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

1

Maintain one incrementing counter

Maintain a single, monotonically increasing counter for the i field on each socket.

2

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.

3

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.

4

Never reuse an ID on retry

Never hand-write the same ID twice. If you retry a request, give the retry a fresh ID.

Tradovate WebSocket request payload showing a unique incrementing request ID in the i field

Fixing Request Floods and the 24-Hour Limit

1

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.

2

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.

3

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.

4

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.

Reconnecting a Tradovate WebSocket and re-sending the authorize frame before the 24-hour limit

Troubleshooting Table

Symptom / error What it means Fix
Socket closes after ~10 seconds of silenceNo client heartbeat; server closed the idle connectionSend an empty-array [] heartbeat every 2.5s
Feed dies the moment the tab goes to backgroundBrowser throttled setInterval / setTimeoutUse timestamp-based heartbeats or a Web Worker
Live data stops but socket "looks" connectedServer stopped its own heartbeats while streaming; client sent noneKeep sending client heartbeats even while streaming
Responses mismatch or requests hangDuplicate integer i (request ID) valuesUse one atomic, incrementing request-ID counter
Connection drops after a burst of framesToo many requests sent too rapidlyQueue and pace outbound requests
Connection drops around the 24-hour markSingle connection held past its lifespanReconnect, re-authorize, and resubscribe well inside 24h
Re-authorize fails after a reconnectAccess token expiredRenew 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 Trial

Frequently 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.