Sizing an RPC plan from your workload: sustained RPS, burst and heavy-method buckets
A request-per-second plan is sized differently from a credit plan. How to measure a workload, how a token bucket with 2× burst actually behaves, and a worked Solana indexer that lands on a specific tier.
Endpoints and plans for the networks in this post: Solana RPC endpoint · Ethereum RPC endpoint.
Credit-based RPC pricing asks "how many calls will you make this month?". A plan limited by requests per second asks a different question: "how fast do you need to call, and which kinds of calls?". The second question is harder to answer from a dashboard of monthly totals, and easier to get wrong in both directions — overbuying because of a daily peak you could smooth, or underbuying because a reconnect storm is invisible in averages.
Credit-based providers publish per-method weights instead (Helius's credits page, read 2026-09-22, weights a standard call at 1 credit and a DAS call at 10). What is rarely published is a sizing walk-through for a per-second model. This post is one, using Triport's published plan matrix, and it ends with a concrete tier for a concrete workload. For the concepts behind credits versus flat pricing, see RPC credits vs flat pricing.
Measure your workload by category, not in total
An RPS plan does not have one budget. On Triport, every method belongs to a category — for example sol_read_rpc, sol_read_rpc_heavy or eth_read_rpc — and each plan sets a sustained RPS per category. The rate limits reference says each chain splits its methods into roughly eight buckets.
So the first measurement is a split. For a week of real traffic, count requests per second per category, and keep three numbers for each: the typical rate, the busiest sustained minute, and the busiest single second. Every response tells you which bucket it was charged to — the X-RateLimit-Category header names it — so you can classify from your own logs rather than from a method list.
On Solana the split that matters most is ordinary versus heavy reads. Each numeric cell shows sustained RPS / short burst capacity, included at no extra cost:
| Category | Example methods | Trial | Basic | Pro | Business |
|---|---|---|---|---|---|
sol_read_rpc | getAccountInfo, getSignaturesForAddress, getTransaction, getBlock | 20 / 40 | 60 / 120 | 200 / 400 | 600 / 1,200 |
sol_read_rpc_heavy | getProgramAccounts | 2 / 4 | 5 / 10 | 20 / 40 | 80 / 160 |
eth_read_rpc (for comparison) | eth_call, eth_getLogs, eth_getBalance | 10 / 20 | 20 / 40 | 100 / 200 | 250 / 500 |
The heavy bucket is small on purpose. A getProgramAccounts scan can do far more work than an ordinary read, so it gets its own budget instead of a weight. Check heavy-method traffic separately when choosing a plan. The Solana limits page lists the categories for the rest of the method set.
Enterprise contracts set no per-category cap by default. Everything below is about the four published plans.
Sustained vs. burst: how the token bucket behaves
The documented rule is short: burst capacity is 2× the sustained rate, included at no extra cost. There is no quota on the number of bursts: traffic spikes can recur throughout the day or month without a separate allowance or charge. The mechanism is a token bucket:
- the bucket holds up to
2 × sustainedtokens and starts full; - it refills continuously at the sustained rate;
- each request spends one token; each JSON-RPC batch element counts separately.
The two published values describe sustained traffic and short peak capacity:
- Basic
sol_read_rpc: 60 RPS sustained · up to 120 burst. - Pro
sol_read_rpc: 200 RPS sustained · up to 400 burst. - Free
sol_read_rpc: 20 RPS sustained · up to 40 burst.
Burst capacity absorbs short traffic spikes — a retry wave after a brief network error, or a page of users arriving at once. For continuous work, choose a plan whose sustained rate covers your busiest sustained minute, or pace the client to that rate.
There is also no daily quota: the reference states there is no per-day cap and no daily-quota header, and plans carry no credits, compute units or overage. A key that stays inside its per-second budgets can run all month.
Why heavy methods get their own budget
Two workloads with the same request rate can cost a node very different amounts. A per-category plan puts expensive methods in a separate, smaller bucket. getProgramAccounts uses sol_read_rpc_heavy, while getAccountInfo uses sol_read_rpc; each has its own sustained rate and included 2× burst capacity.
It also changes how you design. A heavy call you make once a minute costs almost nothing against a 5-per-second budget; the same call made per user request does not fit any plan. Cache heavy results, refresh them on a timer, and serve reads from the cache.
Reading 429 and the rate-limit headers
A rejected request is a plain HTTP 429, not a JSON-RPC error, with a body that tells you exactly which budget you hit:
{
"error": "rate_limited",
"current_tier": "basic",
"category": "sol_read_rpc",
"limit_rps": 60,
"burst_capacity": 120,
"retry_after_sec": 1
}Successful responses carry the same information as headers — X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Category. Two details from production, both observed on 2026-09-22 with a key on a plan that has no per-category cap: the category header names the bucket (sol_read_rpc, eth_read_rpc, polygon_read_rpc), and the limit and remaining headers read -1, the gateway's value for "no per-second budget here". The same -1 appears on DAS calls on every plan, because DAS is gated by plan rather than metered per second.
A client that honours these needs three rules:
- On
429, waitRetry-Afterseconds and spread the retries out. Retrying every rejected request immediately turns a spike into a longer spike. - Pace ongoing work to the sustained rate. Use
X-RateLimit-Remainingto help schedule requests and keep short traffic spikes separate from continuous workloads. - Count a JSON-RPC batch as its members. Size by the calls inside a batch, not by HTTP requests; batching saves round trips, not budget.
A worked example: a Solana indexer
A service indexes activity for 40 program-owned accounts and serves a dashboard. From a week of logs:
- it polls
getSignaturesForAddressfor each of the 40 accounts every 2 seconds: 20 per second; - it fetches each new transaction with
getTransaction, about 30 per second at the busiest sustained minute; - it refreshes three
getProgramAccountssnapshots every 10 seconds: 0.3 per second of heavy reads, arriving as 3 at once; - after a restart or reconnect it has a backlog of about 3,000 reads, which it clears at 50 per second on top of the steady 50: 100 reads per second for about a minute.
Checking each bucket against the plans:
| Need | Rate | Trial | Basic | Pro |
|---|---|---|---|---|
| Steady reads | 50 / s | 20 — no | 60 — yes, 10 of headroom | 200 — yes |
| Heavy snapshots | 3 at once, 0.3 / s | 2 (burst 4) — tight | 5 (burst 10) — yes | 20 — yes |
| Catch-up reads | 100 / s for a minute | above sustained rate | above sustained rate | yes |
Basic covers this indexer's day-to-day sustained traffic and includes short burst capacity up to 120. For a continuous catch-up, either pace total reads to Basic's 60 per second — the steady load keeps 50, the backlog gets the remaining 10, and 3,000 backlog reads take about 5 minutes — for $20 a month; or choose Pro at $249, where 100 per second is half the sustained budget. Choose based on the recovery time you need after an outage.
The 7-day trial fits neither the steady load nor production use. It is a way to measure these numbers on your own traffic before choosing, limited to one key in the EU region.
When this is the wrong approach
- Your load is tiny and spiky. A few thousand calls a day with rare bursts may be cheaper on a small credit plan; per-second plans pay for readiness.
- You need one number for finance. RPS plans map poorly onto a per-call cost line. The pricing page shows what a plan costs if a category runs at its cap for a whole month, which is the closest equivalent.
- Transaction submission dominates. Sends are metered in their own buckets, which this example leaves out; on Solana, submission is not yet a generally available product on Triport.
- You have not measured. Estimates from method counts in code are usually off by the retry and reconnect behaviour you forgot. Measure a week first; the RPC cost calculator is for comparing plans once you have the numbers.
Sources
- Triport, rate limits and tiers: per-category sustained RPS, 2× burst,
429 rate_limitedbody fields,Retry-After: 1, rate-limit headers, no daily quota, 7-day EU-only trial with one token. - Triport, Solana limits and Ethereum limits:
sol_read_rpc20 / 60 / 200 / 600,sol_read_rpc_heavy2 / 5 / 20 / 80,eth_read_rpc10 / 20 / 100 / 250 (trial / Basic / Pro / Business). Plan prices from pricing: Basic $20, Pro $249. - Triport gateway: the burst is a token bucket with capacity equal to twice the sustained rate, refilled at the sustained rate. Rate-limit headers observed on production on 2026-09-22 (
X-RateLimit-Categorypresent;-1on a key with no per-category cap and on DAS calls). - Helius, Credits — https://www.helius.dev/docs/billing/credits, read 2026-09-22 (1 credit per standard call, 10 per DAS call).
- Arithmetic: 40 ÷ 2 = 20; 20 + 30 = 50; 3 ÷ 10 = 0.3; backlog 50 × 60 = 3,000; burst capacity = 2 × sustained RPS; paced catch-up on Basic 3,000 ÷ (60 − 50) = 300 seconds.