Skip to main content

Which cubes support subscriptions

Every cube on EVM, Solana, Trading and Tron appears on the subscription schema. A subscription against any of them is a valid document and the server accepts it.

That does not mean every cube pushes data.

A valid subscription is not a working subscription

Three cubes accept your subscription and then disconnect you under load. Five accept it and never send a single message. In both cases you get no error from the schema, no rejection at subscribe time, and nothing in your logs except silence. This page tells you which is which.


The three behaviours​

BehaviourWhat you seeWhat to do
StreamsMessages arrive within secondsNothing, it works
Needs a filterSome messages, then the socket closes with code 1013Add a where filter, consume asynchronously
Query-onlySocket stays open, no message ever arrivesUse a query, or stream a different cube

Matrix​

Relative volume is a rough guide to what your consumer has to keep up with, not a throughput guarantee.

Solana​

CubeSubscriptionVolume
BlocksStreamsHigh
TransactionsStreamsHigh
TransfersStreamsHigh
TokenSupplyUpdatesStreamsHigh
DEXPoolsStreamsHigh
DEXTradesStreamsModerate
DEXTradeByTokensStreamsModerate
RewardsStreamsModerate
DEXOrdersStreamsLow
PerpetualOrdersStreamsModerate
PerpetualFillsStreamsLow
PerpetualPositionsStreamsLow
PerpetualPricesStreamsLow
PerpetualMarketSummariesStreamsLow
InstructionsFilter requiredVery high
BalanceUpdatesFilter requiredVery high
InstructionBalanceUpdatesFilter requiredVery high

EVM​

CubeSubscriptionVolume
MinerRewardsStreamsHigh
EventsStreamsModerate
TransactionsStreamsModerate
TransfersStreamsModerate
BlocksStreamsLow (block cadence)
CallsStreamsLow
DEXTradesStreamsLow
DEXTradeByTokensStreamsLow
DEXPoolEventsStreamsLow
DEXPoolSlippagesStreamsLow
TransactionBalancesStreamsLow
PredictionTradesStreams (network: matic)Moderate
PredictionSettlementsStreams (network: matic)Moderate
PredictionManagementsStreams (network: matic)Low
BalancesQuery-only—
HoldersQuery-only—
UnclesQuery-only—

Trading​

CubeSubscriptionVolume
TradesStreamsVery high
PairsStreamsVery high
CurrenciesStreamsVery high
TokensStreamsVery high

All four Trading cubes are among the busiest streams on the platform. Filter them.

Tron​

CubeSubscriptionVolume
TransfersStreamsModerate
TransactionsStreamsModerate
DEXTradeByTokensStreamsLow
EventsStreamsLow
BlocksStreamsLow (block cadence)
CallsStreamsLow
DEXTradesStreamsLow
BalancesQuery-only—
HoldersQuery-only—

Filter-required cubes and close code 1013​

Solana.Instructions, Solana.BalanceUpdates and Solana.InstructionBalanceUpdates carry every instruction and every balance change on Solana. Subscribing without a filter asks for the entire firehose, and when your client cannot drain the socket fast enough the server closes it:

close code 1013 — client is not consuming messages fast enough

1013 is "Try Again Later" in the WebSocket spec. Nothing is wrong with your query. The server is shedding a consumer that fell behind.

The failure is worse than a clean error because it is load-dependent. The same unfiltered subscription can run fine during a quiet minute and get dropped during a busy one, so it passes in development and fails in production.

The fix​

Add a where filter so the server sends you only what you need. An unfiltered BalanceUpdates subscription is dropped; the same subscription narrowed to a single token runs cleanly:

subscription {
Solana {
BalanceUpdates(
where: {
BalanceUpdate: {
Currency: { MintAddress: { is: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v" } }
}
}
) {
BalanceUpdate {
Amount
Currency { Symbol }
Account { Address }
}
}
}
}

The same applies to Instructions. Filter by program:

subscription {
Solana {
Instructions(
where: {
Instruction: { Program: { Address: { is: "675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8" } } }
}
) {
Block { Time }
Transaction { Signature }
Instruction { Program { Method } }
}
}
}

Filtering is not only a throughput fix. It is also cheaper, since you are not paying to receive rows you discard.

Also drain the socket asynchronously​

A filter reduces the rate; it does not make a blocking consumer safe. Push each message onto a queue and process it elsewhere, so parsing or database writes never stall the read loop. See Reconnect automatically after disconnect for a working consumer and reconnect loop.


Query-only cubes​

These accept a subscription and never emit, and the reason is structural. Balances and Holders are backed by aggregate-state tables (balances_by_address and balances_by_currency) holding daily balance aggregates rather than individual changes. A daily grain has no per-event row to push, so there is nothing for a subscription to deliver.

That is also what makes them fast to query and what gives them combined support, so the trade-off is deliberate rather than a gap.

Stream the changes, query the state

For a live view, stream Transfers (or TransactionBalances on EVM) and apply the deltas yourself. Use Balances and Holders for the starting state and for periodic checks.

CubeUse instead
EVM.BalancesQuery it on a schedule, or stream EVM.TransactionBalances / EVM.Transfers and apply deltas
EVM.HoldersQuery it on a schedule; stream EVM.Transfers for the token to know when to refresh
Tron.BalancesQuery on a schedule, or stream Tron.Transfers
Tron.HoldersQuery on a schedule, or stream Tron.Transfers
EVM.UnclesQuery with dataset: archive. Ethereum has produced no uncles since the Merge

The pattern for a live balance is to read the balance once, then keep it current from the transfer stream, rather than polling the balance cube in a loop.


Cubes that need a specific network or dataset​

Some cubes exist on the EVM root but only carry data on one network or one dataset. The error message is the only place this is stated today, so it is worth listing:

CubeRequirement
EVM.PredictionTradesnetwork: matic
EVM.PredictionManagementsnetwork: matic
EVM.PredictionSettlementsnetwork: matic
EVM.Unclesdataset: archive
EVM.TransactionBalancesrealtime only, no archive tables

Querying EVM.PredictionTrades on network: eth returns no data available yet to query dataset realtime eth for PredictionTrade, which reads like an outage but is a routing mistake.


How this was measured​

Every row was tested against wss://streaming.bitquery.io/graphql with the graphql-ws subprotocol, one socket per cube, using a minimal selection set generated from schema introspection. Cubes that produced nothing in the first pass were retried on a longer window, because some low-frequency cubes take longer than 20 seconds to deliver their first message.

Classification rules:

  • Streams — at least one message on a socket held open long enough for the cube's cadence.
  • Filter required — reproducibly closed with 1013 when unfiltered, and delivered normally once a where clause was added.
  • Query-only — no message and no error across repeated runs, while control subscriptions on the same chain in the same session delivered normally.

The controls matter: a chain-level failure would have shown up as every cube on that chain going quiet, and that did not happen.


Build with Bitquery

Ready to run this in production?

Get an API key and run these queries in minutes, or talk to us about plans and enterprise delivery.