Skip to content

Snapshots vs. streams

Two ways to read state from the API. Pick the right one or you'll either burn rate-limit or lag the market.

You wantUse
One snapshot at app bootSnapshot RPC (ListPairs, GetBook, MakerService.GetBalance)
Continuous live updatesStreaming RPC (MarketDataService.Subscribe / SubscribeFills / SubscribeMarketSnapshots, MakerService.SubscribeBalance / SubscribeFills / SubscribeMarketSnapshots, TxService.SubscribeBlockhash/SubscribeSlots/SubscribeTxStatus)
Historical backfillHistoricalService.GetTrades / GetCandles

Streaming RPCs are long-lived. The SDK helpers (Client::subscribe_market_data, Client::subscribe_market_data_fills, Client::subscribe_market_data_snapshots, Client::subscribe_maker_balance, Client::subscribe_maker_fills, Client::subscribe_maker_market_snapshots, Client::subscribe_tx_status, Client::spawn_chain_tip, etc.) reconnect and fan out automatically; let HTTP/2 multiplex the rest of your traffic on the same channel.

Cadence

Snapshots are bucket-counted per IP. Streams are not. Recommended ceilings for snapshot RPCs:

OperationSuggested cadence
ListPairsOnce at boot, then on schema changes
GetBook (per pair)Once at boot + once per reconnect
MakerService.GetBalanceOnce at boot + once per reconnect; otherwise use SubscribeBalance
HistoricalService.GetTradesAs needed for backfill

If you find yourself polling above ~1 Hz, switch to a stream.

The boot pattern

For any UI or bot:

  1. ListPairs — discover what's tradeable.
  2. GetBook for each pair you care about — populate local book.
  3. Subscribe to those pairs — apply deltas to the local book.
  4. On reconnect, call GetBook again before re-applying stream events — you may have missed deltas in flight.

The same pattern applies to MakerService (snapshot via GetBalance, deltas via SubscribeBalance; matching SubscribeFills and SubscribeMarketSnapshots streams are scoped to the authenticated maker) and to TxService.SubscribeTxStatus (no snapshot — just open the stream when you start submitting).

Backoff on rate-limit

RESOURCE_EXHAUSTED means the per-IP bucket emptied. Honour it; do not retry tighter. Suggested policy: exponential backoff starting at 500 ms, capped at 30 s — same schedule the SDK's backoffDuration helper returns.

Don't poll the same data over two surfaces

Subscribing to MarketDataService.Subscribe for a pair AND polling GetBook for the same pair just doubles your bandwidth. Subscribe for the live deltas and only call GetBook on a fresh boot or after a stream drop.

Build on Solana