Cube Runner

Plan differences, block sources, the long-term storage queue and history depth for getBlock requests to constant-k Solana RPC endpoints.

Cube Runner answers every getBlock request sent to a constant-k Solana RPC endpoint, in each region. It serves blocks from the region's cache, the region's ledger and the caches of other regions. On Blade Runner and Nexus tier plans, it also retrieves blocks from long-term storage, which holds every block since genesis.

There is no separate endpoint and no client change. Parameters and responses are those of standard getBlock, and the response is byte-identical whichever source serves it.

Plan comparison

Free, OperatorBlade RunnerNexus
getFirstAvailableBlock returnsThe oldest block from which the region holds every later block, in its cache or its ledger. Older blocks are still returned when a cache in any region holds them.0, the genesis block0, the genesis block
Retrieval rate from long-term storage, per regionNot included1 block per 15 seconds1 block per 3 seconds
Monthly allowance per API key, per regionNot applicable10,000 blocks50,000 blocks
Blocks queued per API keyNot applicable200500
Blocks queued per regionNot applicable1,0002,000
Longest allowed queue time (no guaranteed delivery; request again to requeue)Not applicable1 hour2 hours
  • The monthly allowance counts only blocks retrieved from long-term storage for that API key. Blocks served by a cache, a ledger or another region never count.
  • Each region keeps its own count, so an API key has the full allowance in each region.
  • The allowance resets at 00:00 UTC on the first day of each month.
  • The getBlock rate limit in Plans & Limits applies to every getBlock request, whichever source serves it.

Lookup order

Each request is answered by the first source that holds the block.

OrderSourceHoldsPlans
1Region cache, memory then diskRecent blocks, and older blocks that are requested often. The depth depends on stored data, so it varies with block size and between regions.All
2Region ledgerThe ledger windowAll
3Cache of another regionBlocks in that region's cacheAll
4Long-term storageEvery block since genesisBlade Runner, Nexus

A region asks another region only when that region holds the block. Each region also copies, in the background, the blocks it is missing from the caches of the other regions, as far back as its own cache can hold.

Free and Operator tier plans

On Free and Operator tier plans, a getBlock request for a block that no cache, ledger or other region holds returns code -32001 with HTTP 200. The message and data.firstAvailableBlock carry the value getFirstAvailableBlock returns: every block from that slot onward can be retrieved.

{
  "jsonrpc": "2.0",
  "error": {
    "code": -32001,
    "message": "Block 250000000 not available on this tier. First available block: 452746590",
    "data": { "slot": 250000000, "firstAvailableBlock": 452746590, "reason": "tier" }
  },
  "id": 1
}

Long-term storage

On Blade Runner and Nexus tier plans, Cube Runner retrieves a block from long-term storage when no cache, ledger or other region holds it. Each plan has its own queue in each region, shared by every API key on that plan in that region. The retrieval rate and queue limits for each plan are in Plan comparison.

  • A block requested by several API keys at once is retrieved once.
  • A retrieved block is held in the region for at least 15 minutes and served from there to any API key on any plan. More recent blocks are held longer.
  • Blocks that are requested often are kept longer. When space is needed, the oldest blocks leave first, but a block requested several times in the last few hours stays until requests for it stop.

Queued requests

BlockResponse
Retrieved within 25 seconds of the requestThe block, HTTP 200
Not retrieved within 25 secondsHTTP 429 with a Retry-After header and code -32019. The block stays queued.
{
  "jsonrpc": "2.0",
  "error": {
    "code": -32019,
    "message": "Block 250000000 is being retrieved from long-term storage; retry in 30 seconds",
    "data": { "slot": 250000000, "retryAfterSecs": 30, "queuePosition": 2 }
  },
  "id": 1
}
  • Retry-After is between 1 and 60 seconds.
  • Repeating the request after Retry-After returns the block once it has been retrieved.
  • A queued block is dropped when no request for it arrives for 150 seconds. The next request queues it again.

Responses that are not queued

When a block was not queued, was dropped from the queue, or was not returned by long-term storage, the response also carries HTTP 429, a Retry-After header and code -32019. data.reason names the cause.

data.reasonCause
queue_fullThe region's queue for the plan is full. The block was not queued.
key_fullThe API key already has the plan's number of blocks queued: 200 on Blade Runner, 500 on Nexus. The block was not queued.
key_monthlyThe API key has used its monthly allowance in the region. Retry-After is 60. The allowance resets at the start of the next month.
droppedThe queued block reached the plan's longest allowed queue time before it was retrieved. Delivery is not guaranteed; the next request queues the block again.
failedLong-term storage did not return the block.

Client handling

  1. On HTTP 429 with code -32019, wait the number of seconds in Retry-After, then send the same request again.
  2. Repeat each queued request within 150 seconds, or the block is dropped from the queue.
  3. Treat only -32007 and -32009 as skipped slots. Code -32019 and HTTP 429 mean the block has not been served yet.
ClientBehaviour on HTTP 429
solana-client RpcClient (Rust)Retries up to 5 times and waits for Retry-After when it is under 120 seconds. The default request timeout is 30 seconds.
@solana/web3.js 1.x ConnectionRetries 4 times with its own backoff of 0.5 to 4 seconds. Ignores Retry-After.
@solana/kitDoes not retry. The error carries the response headers.

Retrieval order

  1. API keys on the plan take turns.
  2. On an API key's turn, Cube Runner retrieves the key's queued block that the most API keys are waiting for. Repeated requests from one API key do not add to that count.
  3. Among blocks with the same count, the newest block is retrieved first.

An API key gets fewer turns as its repeat count grows.

Repeat requests

Cube Runner records which blocks each API key received in the last 24 hours. Requesting a block again costs nothing while a cache holds it. An API key that makes Cube Runner retrieve a block again from long-term storage, after it already received that block, builds up a repeat count, which reduces its turns in the long-term storage queue.

RuleValue
Requests that never countEvery request served by a cache, a ledger or another region, however often the same block is requested
A request that countsOne that retrieves again from long-term storage a block the API key received in the last 24 hours: adds 2 to the repeat count
DecayThe repeat count halves every 6 hours
Repeat countTurns in the long-term storage queue, compared with an API key whose repeat count is 0
50Half as many
150A quarter as many

The repeat count affects only these turns. Requests served by a cache, a ledger or another region are never delayed by it.

History depth

MethodBehaviour
getFirstAvailableBlockReturns the oldest block from which every later block can be retrieved with getBlock. The value for each plan is in Plan comparison.
minimumLedgerSlotReturns the oldest slot the region's ledger holds. That slot is the history depth for getTransaction and getSignaturesForAddress.
getTransaction, getSignaturesForAddressNot served by Cube Runner. Their history ends at the region's ledger window.

On this page