Raw shreds are one of the earliest ways to receive Solana block data.
Before data becomes reconstructed, decoded, indexed, streamed through Geyser, or exposed through a higher-level API, it starts as raw shred packets moving through the network.
But measuring raw shred performance correctly is easy to get wrong.
We have seen this many times: teams compare two feeds, get numbers that look precise, and then make decisions based on a benchmark that was not actually measuring raw shred latency.
The most common issue is simple: the benchmark accidentally measures the local setup, the decoding pipeline, or the wrong timestamp instead of the arrival time of the same raw shred packet.
That is why we published an open-source Solana shred latency benchmark: a small tool that compares raw shred sources at the packet level and shows which source delivered the same shred first.
What should a raw shred benchmark measure?
A clean raw shred benchmark should answer one narrow question:
For the same Solana shred, which source delivered the packet to this machine first?
So not which decoded transaction appeared first, or which pipeline emitted an event first, or which source delivered a reconstructed transaction first.
The benchmark should compare the arrival time of the same shred packet across different sources. The shred is identified by its ShredId: slot, index, and type.
Once the same shred is seen from multiple sources, the benchmark can measure:
- which source delivered it first;
- how often each source wins;
- how far behind the other sources were;
- what the p50, p90, and p99 delay look like when a source loses.
This sounds simple, but there are several common mistakes that can make the result misleading.
Mistake 1: treating different ports as equal
A common setup is to send one raw shred source to one UDP port and another source to a different UDP port.
For example:
- source A sends to port
20000; - source B sends to port
20005.
Then the benchmark compares which port receives each shred first.
This can be a valid test, but it needs to be interpreted carefully.
Different ports are not always treated equally by the host. Local effects can influence reception speed:
- proxy configuration;
- process scheduling;
- thread priorities;
- interrupt handling;
- queueing;
- buffering;
- packet fanout;
- temporary interruptions;
- different relayer paths.
At very low latency, these details matter.
If one port is processed more favourably than another, the result may say that one source is faster when the benchmark is actually measuring a local delivery-path difference.
This does not mean port-based benchmarking is useless. It means the conclusion should be precise.
If each source lands on its own port, you are measuring the full path into that port. That can be exactly what you want when comparing two proxies, two relayers, or two local delivery setups.
But if the goal is to compare providers directly, often a cleaner setup is to send multiple sources to the same port and group them by source IP.
Mistake 2: comparing decoded transactions instead of raw shred arrival
Another common mistake is using decoded transactions as the benchmark output.
In the end, most teams do need decoded transactions. But decoded transaction latency is not the same thing as raw shred delivery latency.
Once raw shreds enter a decoding pipeline, many extra variables are introduced:
- how shreds are buffered;
- how entries are reconstructed;
- how transactions are extracted;
- how decoding work is scheduled;
- whether decoding is optimized;
- whether both sources use the same pipeline;
- whether one path has more queueing or contention;
- whether duplicate work is happening across threads.
If two raw shred feeds are decoded in two separate pipelines, the benchmark can become dominated by decoding behaviour rather than raw packet arrival.
This is especially dangerous when the decoding setup is not representative of production.
In a normal optimized setup, teams usually do not decode the same data twice in two separate unoptimized paths and then compare those two outputs. They build one optimized pipeline and process the fastest available data as efficiently as possible.
So if the goal is to compare raw shred delivery, decoding should not be part of the measurement.
Measure raw packet arrival first. Measure decoding separately.
Mistake 3: comparing raw shreds to decoded transactions
This is even worse.
A raw shred packet and a decoded transaction are different stages of the data lifecycle.
A shred arrives first. Then it needs to be collected, reconstructed, decoded, and exposed as transactions or entries.
If one source is measured at raw shred arrival and another source is measured after transaction extraction, the benchmark mixes several different layers:
- network delivery;
- shred arrival;
- reconstruction;
- decoding;
- transaction extraction;
- application-level processing.
That does not answer a clean question.
If you want to compare raw shred sources, compare raw shreds.
If you want to compare decoded transaction streams, compare decoded transaction streams.
Do not mix both layers in the same benchmark.
Mistake 4: counting junk shreds as wins
Another issue is junk or unverified shreds.
We have seen cases where a feed looks fast because it sends packets early, but some of those packets (sometimes over 20% of shreds) cannot actually be verified or reconstructed into useful data.
That can distort latency results.
If the first packet for a shred source is not usable, it should not be treated the same as a valid shred that actually matters for downstream processing.
This is why our benchmark supports a clean filtering mode.
With:
--shred-filter clean
the tool verifies each shred against the slot leader and drops junk or unverified packets before scoring. This makes the benchmark stricter: the win rate is calculated only from shreds that pass verification.
The default mode is:
--shred-filter all
This counts every parsed shred and is useful for basic testing. But when comparing providers seriously, the clean filter gives a better view of useful raw shred performance.
Mistake 5: scoring immediately after the first packet
A raw shred benchmark should not finalize the result immediately when the first source delivers a shred.
If it does, slower copies from other sources may be counted as missing even though they arrived a few milliseconds later.
That creates false drops.
Instead, each shred should be held briefly before scoring. This gives other sources time to deliver the same shred, so the benchmark can record them as delayed matches rather than missing data.
Our benchmark uses a settle window for this:
--settle-window-ms 1000
The default 1000ms window is conservative. It should be larger than the maximum arrival skew you expect between sources.
The point is not to add latency to the measurement. The point is to wait long enough to score the same shred fairly across all sources.
Our open-source Solana shred latency benchmark
We published solana-shred-perf to make raw shred benchmarking simple and reproducible.
The tool uses libpcap to passively capture Solana shred packets off the wire. It does not bind to the port, so it can run alongside your validator, proxy, relayer, or application without taking over the traffic.
For every shred it sees, the tool:
- captures the UDP packet;
- extracts the Solana
ShredId; - records the first arrival per source;
- ignores duplicate arrivals from the same source;
- waits for the settle window;
- finalizes the comparison;
- prints win rate and delay percentiles.
The benchmark is intentionally narrow.
It measures which source delivered the same raw shred packet first.
That is what makes the result useful.
Two ways to compare sources
The tool supports two modes.
raw-ips: compare source IPs on one shared port
This is the recommended setup when several upstreams can send to the same destination port.
All sources land on the same port, and the benchmark groups packets by source IP.
Example:
sudo RUST_LOG=info ./target/release/solana-shred-perf \
--interface any \
--ports 20000 \
--mode raw-ips \
--report-interval-secs 20 \
--settle-window-ms 1000 \
--label 198.13.137.171=shreder.xyz
This setup helps reduce local port-related bias because all sources are received through the same destination port.
raw-ports: compare destination ports
Use this mode when each source writes to its own port.
Example:
sudo RUST_LOG=info ./target/release/solana-shred-perf \
--interface any \
--ports 20000,20005 \
--mode raw-ports \
--report-interval-secs 20 \
--settle-window-ms 1000
This is useful when comparing full delivery paths, such as:
- proxy A vs proxy B;
- one provider path vs another provider path;
- two local receiving setups.
Just remember: in this mode, the result is about the full path into each port, not only the external provider.
Filtering for clean shreds
For stricter tests, use:
sudo RUST_LOG=info ./target/release/solana-shred-perf \
--interface any \
--ports 20000 \
--mode raw-ips \
--shred-filter clean \
--rpc-url https://api.mainnet-beta.solana.com
The clean filter uses RPC to fetch the leader schedule and verifies shreds against the slot leader.
This is useful when you want the benchmark to ignore packets that are parsed but not actually valid for clean downstream use.
For quick local checks, --shred-filter all is usually enough. For provider comparisons, clean is the safer mode.
How to read the output
A typical result looks like this:
╔═════════════════════════════════════════════════════════════════════════════════════════════════╗
║ Shred Latency by port - 20.0s ║
║ Finalized: 296134 Pending: 812 Settle: 1000ms ║
╠══════════╦═══════════╦════════╦══════════╦══════════╦══════════╦══════════╦══════════╦══════════╣
║ Port ║ Matched ║ Win % ║ p10 ║ p30 ║ p50 ║ p70 ║ p90 ║ p99 ║
╠══════════╬═══════════╬════════╬══════════╬══════════╬══════════╬══════════╬══════════╬══════════╣
║ 20000 ║ 148233 ║ 61.4% ║ 0µs ║ 0µs ║ 0µs ║ 180µs ║ 640µs ║ 2.10ms ║
║ 20005 ║ 147901 ║ 38.6% ║ 0µs ║ 90µs ║ 310µs ║ 720µs ║ 1.50ms ║ 4.20ms ║
╚══════════╩═══════════╩════════╩══════════╩══════════╩══════════╩══════════╩══════════╩══════════╝
A/B summary: port 20000 wins 61.4% vs port 20005 wins 38.6%. Loser p50=310µs, p99=4.20ms.
The key fields are:
- Matched — how many finalized shreds this source received.
- Win % — how often this source delivered the shred first. Higher is better.
- p10–p99 — how far behind the winner this source was.
When a source wins, it contributes a 0µs sample. This is why a source with a high win rate may show 0µs across lower percentiles. The tail percentiles show what happens when the source loses.
For latency-sensitive systems, both parts matter.
A source can win often but still have a bad tail when it loses. Another source can win less often but stay very close when it is not first.
A useful benchmark should show both win rate and delay distribution.
What this benchmark does not measure
This tool does not measure everything.
It does not measure:
- reconstruction speed;
- transaction decoding speed;
- Geyser delivery latency;
- application-level processing;
- end-to-end trading performance.
Those are important, but they are different benchmarks.
This tool measures one thing:
Which source delivered the same raw Solana shred packet to your machine first?
That narrow scope is intentional.
If you want to know which raw shred source reaches your host first, this is the cleanest thing to measure.
Recommended benchmark setup
For the cleanest comparison:
- Run all sources on the same host.
- Use
raw-ipswhen multiple sources can land on one shared port. - Use
raw-portsonly when each source must use a separate port. - Add labels so the output is easy to read.
- Use a settle window large enough to avoid false drops.
- Use
--shred-filter cleanfor serious provider comparisons. - Avoid decoding during the raw shred delivery benchmark.
- Run the test over multiple reporting periods.
- Compare Win %, p50, p90, and p99 together.
Latency is always path-dependent.
Your region, machine, NIC, kernel, proxy, provider path, and local configuration can all affect the result. That is why the best benchmark is the one you can run yourself on your own infrastructure.
Why we built this
At Shreder, we work on ultra-low-latency Solana data delivery: raw shreds, decoded shreds, Binary, Preconfs, and Geyser/Fastlane.
All of these systems depend on one basic principle: the earlier and cleaner the data arrives, the better the downstream system can perform.
But benchmarking has to be done carefully.
We have seen too many raw shred benchmarks that compare the wrong layers, include decoding effects, treat different local paths as equal, or count packets that are not actually useful.
The goal of this tool is to make the basic raw shred comparison simple:
- same shreds;
- same machine;
- packet-level timestamps;
- clear win rate;
- clear p50, p90, and p99;
- optional clean-shred filtering.
Try it on GitHub
We published the Solana Shred Latency Benchmark as an open-source tool for validators, relayers, infra teams, and latency-sensitive Solana developers.
Use it to compare raw shred providers, validate routing, test proxy setups, or understand whether a second source actually improves your latency.
You can find the tool on GitHub:
And if you want to test Shreder's low-latency Solana data feeds, get started at console.shreder.xyz.