Skip to main content
gRPC streams on Polymarket US are long-lived connections. Open the stream, keep it open, and apply every message. A reconnect is for a dropped connection, not a polling loop.
A short deadline on Drop Copy is not a reconnect strategy.Opening CreateDropCopySubscription every few seconds and cancelling it a few seconds later never catches up. Each reconnect starts a replay from your last resume_token. If you cancel before that replay finishes, the next connect starts the same replay again.Do not put a 5–10 second deadline on a streaming RPC. Do not open one Drop Copy stream per order. The request has no order id.

One Drop Copy

Empty symbols is the whole firm. One leader-elected consumer per environment.

Commit, then resume

Persist resume_token only after every execution in that batch is durable. Dedup on execution.id.

20 streams total

The 20 concurrent-stream budget is pooled across all gRPC subscriptions, not 20 per RPC.

How many streams

Full numbers: Rate Limits.
Need market data on more than 1000 symbols? Do not open 80 streams. Use symbols=[] for the full book, or one bidirectional market-data stream and add symbols there. Stay inside the 20 concurrent-stream budget for Drop Copy, orders, ledger, RFQ, and market data together.

Snapshot vs resume

Not every stream starts with a snapshot. Do not copy a snapshot client onto Drop Copy. Unary reads (SearchExecutions, SearchTrades, GetOrderBook) are anchors, not a substitute for the stream. See Reconciliation.

The reconnect-cancel loop

A behind resume_token is normal after a restart. The server replays from that point up to live. Replay can take longer than a few seconds.If the client sets a short RPC deadline, or a 10-second “no message means dead” timer that fires during replay, it cancels the stream. The next connect uses the same behind token. Replay starts over. You never reach live, and the exchange keeps replaying.
  1. Open one Drop Copy stream with symbols=[].
  2. Do not set a per-RPC timeout of a few seconds.
  3. Apply each batch, then persist response.resume_token.
  4. On UNAVAILABLE or a real disconnect, back off and reconnect with that token.
  5. Treat CANCELLED you caused (process restart, deadline) as your bug, not a signal to hammer reconnect.

Do / don’t

CreateOrderSubscription over 1000 symbols is not the market-data cap. Market data over 1000 is INVALID_ARGUMENT (at most 1000 symbols per subscription). Hitting RESOURCE_EXHAUSTED on a stream is the 20 concurrent-stream budget, ingress rate, or a too-large message — not the 1000 check. Details: Order stream.

Limits that matter here

See Rate Limits and Authentication.
Access tokens expire in 3 minutes. Refresh the token in the background. Use the new token on the next connect. Do not tear down a live stream every 3 minutes to “re-auth.” The streaming RPC is authenticated when it starts.

Client shape

Wrong

apply_batch must be idempotent. Delivery is at-least-once. Use execution.id (and trade_id on fills) as the unique key.

FIX Drop Copy

If you consume fills on FIX instead of gRPC, that is one Drop Copy session, not a gRPC stream per order. See FIX Drop Copy. Do not run a reconnecting gRPC Drop Copy and a FIX DC session against the same work unless you can dedup.

Drop Copy stream

Executions, trade capture, state change, positions

Reconciliation

Streams first, unary reads as anchors

Market data stream

1000-symbol cap, snapshot vs live, keepalive

Rate limits

20 streams, 100 msg/s ingress, RFQ open rate