# Yellowstone gRPC limits (/solana-rpc/grpc/limits)

> Connection, stream, and filter limits for Corvus Yellowstone gRPC on Solana, and which gRPC status and reason each rejection carries.



Cross a limit here and you usually get a gRPC status plus a structured reason naming what you went over, so branch on the reason. One protection skips gRPC altogether: cancel streams fast enough and the connection closes with an HTTP/2 `GOAWAY` carrying `ENHANCE_YOUR_CALM`, no gRPC status and no reason field.

Most of the limits scale with your plan's RPS.

| Limit                                                                                                                      | Value                                         |
| -------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------- |
| Concurrent connections                                                                                                     | `ceil(RPS × 5%)`, minimum 1, capped at **50** |
| `accounts`: account keys, summed across every `accounts` filter                                                            | **RPS**                                       |
| `accounts`: owner keys, summed across every `accounts` filter                                                              | **RPS ÷ 5**                                   |
| `accounts`: data slices                                                                                                    | **10**                                        |
| `transactions`: `account_include` / `account_exclude` / `account_required`, each summed across every `transactions` filter | **RPS** each                                  |
| `slots` filters                                                                                                            | **10**                                        |
| `blocks_meta` filters                                                                                                      | **10**                                        |
| `entry` filters                                                                                                            | **10**                                        |
| Silence timeout                                                                                                            | **20 seconds**                                |

Worked through: on a 500 RPS plan that's 25 connections, 500 account keys or 100 owner keys, and 500 keys in each of `account_include`, `account_exclude` and `account_required`. At 1,000 RPS you get 50 connections, 1,000 accounts and 200 owners.

[NFT pass](/platform/nft-pass) holders are the exception: their caps are flat numbers rather than RPS-derived ones.

| Limit                                                                           |   Pro | Elite |
| ------------------------------------------------------------------------------- | ----: | ----: |
| `accounts` account keys                                                         | 1,200 | 2,000 |
| `accounts` owner keys                                                           |   200 |   200 |
| `transactions` `account_include` / `account_exclude` / `account_required`, each | 1,200 | 2,000 |
| `slots` filters                                                                 |    50 |   100 |

Data slices, `blocks_meta` and `entry` filters stay at 10 either way.

Every filter figure above is a **total, not a per-filter allowance**. Keys are summed across every filter in the request, and that running total is charged to your account (or to your source IP, on an IP-allowlisted endpoint) across every connection you hold to that endpoint. When a `filters` rejection lands it's raised against the connection that sent the offending `SubscribeRequest`, and that request's contribution is rolled back, so your other connections keep running.

If you need a filter set larger than your plan allows, we can arrange it; ask us on [Discord](https://discord.gg/corvus-labs).

The silence timeout is armed by *your* writes, not the server's. If the server has sent nothing for 20 seconds while your client is still writing to the connection, the connection closes, so an application-level keepalive won't prevent it. The fix is a filter wide enough that the server always has something to send.

## Limit classes

| Limit                | What it controls                                         | Failure                                                                                                              |
| -------------------- | -------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
| Connections          | Open gRPC channels                                       | `RESOURCE_EXHAUSTED` (8), reason `connection_limit`                                                                  |
| Concurrent streams   | Active RPC streams on a channel                          | `RESOURCE_EXHAUSTED` (8), reason `stream_limit`                                                                      |
| Filters              | Count and breadth of selectors                           | `RESOURCE_EXHAUSTED` (8), reason `filters`                                                                           |
| Subscription updates | How often a connection rewrites its filter configuration | `RESOURCE_EXHAUSTED` (8), reason `subscribe_rate_limit`                                                              |
| Stream resets        | How fast a connection cancels streams (`RST_STREAM`)     | HTTP/2 `GOAWAY` with `ENHANCE_YOUR_CALM`; the connection is terminated. No gRPC status and no reason string are sent |

The weighted per-method costs in [Solana RPC rate limits](/solana-rpc/limits) don't apply to a stream; streams are metered by connections, streams and filters. RPS, TPS and streaming allowances stay separate.

## The PPS gate (aRPC only)

The packets-per-second gate only runs on the aRPC transport (`http://arpc.<region>.corvus-labs.io:20202`), so nothing on port 10101 will ever see it. It arrives as `PERMISSION_DENIED` (7) with the detail prefix `PPS limit requirement not met`, never as JSON-RPC code `-32100` in an HTTP error body. If you also consume aRPC, [PPS closes the connection](/arpc/limits#the-pps-check) has the requirement and the way out.

## Matching detail strings

Detail strings can carry extra text after the stable prefix, including a trailing support sentence pointing at `discord.gg/corvus-labs`. Compare on status, reason and prefix.

## Handle a rejection

| Symptom                                                         | Cause                                                                                                                 | Fix                                                                                                            |
| --------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- |
| `RESOURCE_EXHAUSTED`, reason `stream_limit`                     | Too many concurrent streams on the channel                                                                            | Close unused streams before opening another                                                                    |
| `RESOURCE_EXHAUSTED`, reason `filters`                          | Filter count or breadth over quota                                                                                    | Narrow the selector; splitting it across connections does not help                                             |
| `RESOURCE_EXHAUSTED`, reason `subscribe_rate_limit`             | Filter configuration rewritten too often                                                                              | Stop rewriting the request; back off, then send one complete configuration                                     |
| HTTP/2 `GOAWAY`, `ENHANCE_YOUR_CALM`                            | Too many stream cancellations in a short window                                                                       | Stop opening and cancelling streams; the connection is terminated, so reopen once                              |
| `RESOURCE_EXHAUSTED`, reason `rate_limit`                       | General allowance exhausted                                                                                           | Reduce load, then retry                                                                                        |
| `PERMISSION_DENIED`, reason `permission_denied`                 | Resource does not include this product                                                                                | Check access; reconnecting cannot fix it                                                                       |
| `INVALID_ARGUMENT` (3), message naming `from_slot`              | The replay request breaks its contract: wrong commitment, a `blocks` filter, or a slot older than the retained window | See [replay on reconnect](/solana-rpc/grpc/usage#reconnect-after-a-failure)                                    |
| `FAILED_PRECONDITION` (9), message beginning `from_slot replay` | Replay wasn't available on the node that took this connection                                                         | Reconnect and retry, or re-subscribe without `from_slot` and backfill through [JSON-RPC](/solana-rpc/json-rpc) |
| `INVALID_ARGUMENT` (3)                                          | Malformed request or filter                                                                                           | Fix the request; do not retry unchanged                                                                        |
| `UNAUTHENTICATED` (16)                                          | Wrong `x-token` or unregistered egress IP                                                                             | See [Access & authentication](/platform/access)                                                                |

[Gateway & streaming errors](/solana-rpc/errors) is the full status and reason reference, and [Pricing](/platform/pricing) lists the preset capacities.
