Bandwidth surprises usually begin with a label such as "transactions" or "all program activity." Those labels hide the only inputs that matter: which messages pass the filter, how large they are, and how often they arrive.
This field note gives you a measurement method and one worked RPCEdge sample. For the filter shapes themselves, use the Yellowstone gRPC filter cookbook.
Start with the conversion you can audit
For a sustained average over 30 days, using decimal units:
GB/day = MB/second * 86.4
TB/month = MB/second * 2.592
1 MB/second sustained ~= 86.4 GB/day ~= 2.59 TB/month
1 TB/month ~= 0.386 MB/second sustained
4 TB/month ~= 1.54 MB/second sustained
10 TB/month ~= 3.86 MB/second sustainedThese conversions are arithmetic, not a forecast. Your measured rate supplies the forecast input.
Small rates compound. A stream averaging 250 KB per second is roughly 648 GB over a 30-day month. A burst to 2 MB per second may still be harmless if it lasts one minute, but it can expose a decoder or queue that was sized only for the average.
One measured Jupiter sample
We ran an early profile through the RPCEdge gateway with these conditions:
| Field | Measured condition |
|---|---|
| Network | Solana mainnet |
| Stream path | RPCEdge preprocessed gRPC |
| Filter | Jupiter account include |
| Sample window | 31 minutes |
| Projected daily traffic | about 4.95 GB |
| Projected 30-day traffic | about 0.15 TB |
| Observed payload ratio | about 941 bytes per matched signature |
The daily projection corresponds to an average near 57 KB per second over that window. It is a small filtered stream compared with a firehose, but the result can move with program activity, message format, traffic mix, and the selected accounts.
What this sample supports: a narrow transaction filter can fit well below multi-terabyte monthly allowances. What it does not support: every Jupiter subscription will use 0.15 TB per month, or a 31-minute window represents the worst traffic your application will see.
The filter changes the bill before the provider does
Yellowstone supports different message classes and server-side filters. The official repository documents account filters by key, owner, data size, and memory comparison; transaction filters by included, excluded, and required accounts; plus account data slices. See the Yellowstone filter reference.
The practical cost order is workload-dependent, but these shapes deserve different tests:
| Subscription shape | Likely traffic shape | First question |
|---|---|---|
One wallet in accountInclude | Narrow, event-driven | Does every mention need full transaction data? |
| One DLMM pool and nearby bin arrays | Narrow to medium | Can exact account keys replace a program-wide filter? |
| One active program | Activity-dependent | Which instructions or accounts can be discarded server-side? |
| SPL Token program activity | Broad | Is a downstream indexer required, or only selected mints and owners? |
| Full blocks or all transactions | Firehose | Can the consumer sustain bursts and recover gaps? |
Do not infer cost from account count alone. One busy pool can emit more traffic than hundreds of quiet wallet accounts.
Measure the subscription you will ship
Use a repeatable runbook:
- Freeze the endpoint region, stream type, commitment, filters, and included fields.
- Run the real decoder and queue, not a client that discards messages before measurement.
- Record received bytes, messages, matched signatures, and the sample duration.
- Capture average and peak bytes per second in at least one busy interval.
- Repeat after changing one filter dimension.
- Project 30-day traffic from the average, then add explicit burst and growth headroom.
Provider usage telemetry is the cleanest measurement because it sees billed gateway bytes. For a local cross-check, isolate the worker in its own container or host and record network receive bytes before and after the test. Container totals include TLS and transport overhead, while serialized application objects measure a different layer. Name the layer in the report.
Use this worksheet:
profile_name:
endpoint_region:
stream_type:
commitment:
filters:
included_fields:
started_at:
duration_seconds:
received_bytes:
messages:
matched_signatures:
average_bytes_per_second:
peak_bytes_per_second:
projected_tb_per_30_days:
measurement_layer: gateway | container_rx | application_payload
known_limitations:The measurement_layer line prevents a common mistake: comparing a provider's network accounting
with the size of JSON produced after decoding.
Cut traffic without removing required data
Apply changes in this order:
- Replace program-wide filters with exact accounts when the watched set is known.
- Exclude vote and failed transactions unless the application needs them.
- Use
accountRequiredwhen one account mention is too permissive. - Slice account data when the decision needs only a stable region of the account layout.
- Split workloads so a UI, indexer, and trading worker do not share one oversized subscription.
- Decode near the stream and hand downstream workers a smaller typed event when raw protobuf data is no longer needed.
Every reduction needs a correctness test. A smaller stream that omits a required state transition is more expensive than the bandwidth it saved.
Capacity includes the consumer, not only the network
Track four rates together:
| Rate | Failure when undersized |
|---|---|
| Network receive | Disconnects, throttling, or host saturation |
| Decode throughput | Queue growth and stale decisions |
| Durable write throughput | Lost checkpoints or growing replay debt |
| Reconciliation throughput | Recovery takes longer than the replay window |
A bot that receives 2 MB per second but decodes 1.5 MB per second has a continuity problem even if the plan includes enough bandwidth. Measure queue age, not only queue length, because stale events can be more dangerous than dropped low-priority events.
Want a bandwidth profile for your filter?
Send us the programs, accounts, stream type, commitment, and region. We can run the same profile method against the subscription shape you plan to deploy.
Publish the conditions with the number
A bandwidth figure without its filter and window is marketing noise. Record the full subscription, measurement layer, average, peak, and limitations. That gives engineering a capacity input and gives finance a forecast it can revisit when activity changes.