Corvus Labs

Shredstream

Receive raw Solana shreds over push-based UDP from Corvus Shredstream: registration, firewall rules, and how to verify packets arrive.

Shredstream pushes native Solana shreds at you as UDP packets. There's no endpoint to dial and no subscribe call: you register a destination during onboarding and we push packets to it. Nothing on the latency stack sees the wire sooner.

Unless your application already parses native shreds and can absorb packet loss, reordering, duplication and Solana shred-format changes, you'll have an easier time on a typed stream: Yellowstone gRPC or aRPC.

How delivery works

PropertyValue
DirectionCorvus โ†’ you. Unsolicited inbound UDP; you never initiate a connection
TransportUDP, push-based, fire-and-forget
SessionNone. No handshake, no subscription message, no acknowledgements, no backpressure
Error channelNone. Nothing reports a failure to you; silence is the only symptom
PayloadNative Solana shreds. You reconstruct the data from them yourself
EncryptionNone
RegionOne, assigned at onboarding

A firewall rule, a changed address and a saturated receive buffer all look identical from where you're sitting.

Nine metros

Shredstream runs in every Corvus metro; Solana RPC covers five of them (Regions).

MetroCode
๐Ÿ‡ฉ๐Ÿ‡ช Frankfurtfra
๐Ÿ‡ณ๐Ÿ‡ฑ Amsterdamams
๐Ÿ‡ฌ๐Ÿ‡ง Londonlon
๐Ÿ‡ฎ๐Ÿ‡ช Dublindub
๐Ÿ‡ฑ๐Ÿ‡น ล iauliaisqq
๐Ÿ‡บ๐Ÿ‡ธ New Yorknyc
๐Ÿ‡บ๐Ÿ‡ธ Salt Lake Cityslc
๐Ÿ‡ธ๐Ÿ‡ฌ Singaporesgp
๐Ÿ‡ฏ๐Ÿ‡ต Tokyotyo

Register a destination

You give Corvus two things at onboarding:

  • A stable public IPv4. Registration is by address, not hostname.
  • One UDP port. That single port carries the whole feed, and Corvus confirms it with you during onboarding.

Have the inbound path open and a socket bound to 0.0.0.0 on that port before the feed is switched on. The registration is static, so if your address or port changes, ask for re-registration on Discord before you cut over.

Ask us for the sender addresses for your assigned region at the same time. The traffic is unsolicited inbound UDP, so most firewalls want a source to allow, and you can't discover it from your side until packets are already arriving. Trials work the same way: give us the region and the IP:PORT you want the feed pushed to.

Firewall and network requirements

The traffic is unsolicited inbound UDP, so it needs an explicit allow rule in every layer that can drop it and a receiver that actually holds the registered address: no source NAT, no shared or dynamic public address, no L7 proxy in the path. Raise SO_RCVBUF and net.core.rmem_max once your counters show receive-buffer errors, not in advance.

Verify traffic is arriving

Run these on the registered destination host itself, on its own network path.

# 1. Are packets reaching the host at all?
sudo tcpdump -n -i any udp port <PORT> -c 20

# 2. Is anything actually listening, and on which address?
sudo ss -lunp | grep ':<PORT>'

# 3. Are you dropping what you receive?
nstat -az UdpInErrors UdpRcvbufErrors UdpNoPorts

tcpdump sees packets before your socket does, which is what makes it the decisive test.

Nothing is arriving

SymptomCauseFix
tcpdump on the destination host shows nothingInbound UDP dropped upstream by a security group, network ACL, or edge firewallAdd an explicit inbound allow for the registered UDP port
tcpdump shows nothing and the host sits behind NATUnsolicited inbound UDP has no NAT state to matchMove the receiver to a routable public IPv4 or a static one-to-one mapping
tcpdump shows packets, the application sees noneSocket bound to 127.0.0.1, bound to the wrong port, or another process holds itBind 0.0.0.0 on the registered port; confirm with ss -lunp
Traffic stopped after an infrastructure changeThe address or port moved; the registration still points at the old oneRe-register the destination on Discord
UdpRcvbufErrors climbing under loadYour receive buffer overflows before you drain itRaise SO_RCVBUF, move parsing off the read loop
UdpNoPorts climbingPackets arrive while nothing is boundKeep the listener up; restarts lose everything sent meanwhile
The same shred twiceExpected; fire-and-forget delivery can duplicateDeduplicate in the receiver
Shreds out of order, or gapsExpected; UDP neither orders nor retransmitsOrder and gap-fill in the receiver; backfill from JSON-RPC if completeness matters

What your receiver needs

A read loop that never blocks on downstream work, a shred parser matching the Solana version you support, and a plan for when that format changes. Alert on no packets for N seconds; it's the only failure signal you get.

You write the decoder

What arrives is native Solana shreds, so reassembly, forward error correction and transaction reconstruction are all yours to implement. We don't ship a decoder or a reference client: the one behind aRPC is part of our service layer rather than a library we distribute. If you want the decoding done for you, aRPC is that product, and the latency stack compares the two.

Teams starting from scratch usually begin from an open-source implementation such as dyodx/unshred. It isn't ours: read it before you run it, and pin a commit you have reviewed.

Shreds are pre-execution

A shred is data the network is propagating, not a result. Receiving one isn't execution, confirmation or finality, and a single packet is never proof you have complete slot data. Anything you act on, confirm through Solana RPC at the commitment level your application requires.

Shredstream, Yellowstone gRPC or aRPC

NeedUse
Filtered account, transaction, slot, or block updates on a typed streamYellowstone gRPC, under Solana RPC (5 metros)
Pre-execution entry, transaction, and slot streams over gRPCaRPC (9 metros)
Native shred processing you implement yourselfShredstream (9 metros)

On this page