# 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.

- Canonical: https://triport.io/blog/rpc-plan-sizing-rps-burst
- Published: 2026-09-22
- Updated: 2026-10-10
- Author: Triport Engineering
- Category: Engineering
- Networks: Solana, Ethereum

## TL;DR

- Size an RPS plan from the busiest sustained minute of each method category, not from a monthly total: reads, heavy reads and any other bucket are metered separately, and each has its own per-second budget.
- Each finite request-rate budget includes 2× short burst capacity at no extra cost. There is no quota on the number of traffic spikes. Size ongoing work to sustained RPS.
- In the worked Solana indexer, 50 reads per second and a few heavy calls fit Basic's 60 and 5; a sustained catch-up at 100 reads per second fits Pro.

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](https://triport.io/learn/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](https://triport.io/docs/rate-limits-and-tiers) 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](https://triport.io/docs/sol/limits) 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 × sustained` tokens 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:

```json
{
  "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:

1. **On `429`, wait `Retry-After` seconds and spread the retries out.** Retrying every rejected request immediately turns a spike into a longer spike.
2. **Pace ongoing work to the sustained rate.** Use `X-RateLimit-Remaining` to help schedule requests and keep short traffic spikes separate from continuous workloads.
3. **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 `getSignaturesForAddress` for 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 `getProgramAccounts` snapshots 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](https://triport.io/pricing) 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](https://triport.io/tools/rpc-cost) is for comparing plans once you have the numbers.

## Sources

1. Triport, [rate limits and tiers](https://triport.io/docs/rate-limits-and-tiers): per-category sustained RPS, 2× burst, `429 rate_limited` body fields, `Retry-After: 1`, rate-limit headers, no daily quota, 7-day EU-only trial with one token.
2. Triport, [Solana limits](https://triport.io/docs/sol/limits) and [Ethereum limits](https://triport.io/docs/eth/limits): `sol_read_rpc` 20 / 60 / 200 / 600, `sol_read_rpc_heavy` 2 / 5 / 20 / 80, `eth_read_rpc` 10 / 20 / 100 / 250 (trial / Basic / Pro / Business). Plan prices from [pricing](https://triport.io/pricing): Basic $20, Pro $249.
3. 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-Category` present; `-1` on a key with no per-category cap and on DAS calls).
4. Helius, Credits — https://www.helius.dev/docs/billing/credits, read 2026-09-22 (1 credit per standard call, 10 per DAS call).
5. 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.

## Try it

- Reference: [Rate limits and tiers — buckets, burst, 429 envelope](https://triport.io/docs/rate-limits-and-tiers)
- Network: [Solana RPC — endpoints, limits and plans](https://triport.io/solana-rpc)
