# Shredstream (/platform/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](/platform/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](/solana-rpc/grpc) or [aRPC](/arpc).

## How delivery works

| Property      | Value                                                                             |
| ------------- | --------------------------------------------------------------------------------- |
| Direction     | Corvus → you. Unsolicited inbound UDP; you never initiate a connection            |
| Transport     | UDP, push-based, fire-and-forget                                                  |
| Session       | None. No handshake, no subscription message, no acknowledgements, no backpressure |
| Error channel | None. Nothing reports a failure to you; silence is the only symptom               |
| Payload       | Native Solana shreds. You reconstruct the data from them yourself                 |
| Encryption    | None                                                                              |
| Region        | One, 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](/platform/regions)).

| Metro               | Code  |
| ------------------- | ----- |
| 🇩🇪 Frankfurt      | `fra` |
| 🇳🇱 Amsterdam      | `ams` |
| 🇬🇧 London         | `lon` |
| 🇮🇪 Dublin         | `dub` |
| 🇱🇹 Šiauliai       | `sqq` |
| 🇺🇸 New York       | `nyc` |
| 🇺🇸 Salt Lake City | `slc` |
| 🇸🇬 Singapore      | `sgp` |
| 🇯🇵 Tokyo          | `tyo` |

## 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](https://discord.gg/corvus-labs) 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.

```bash
# 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

| Symptom                                              | Cause                                                                             | Fix                                                                                                        |
| ---------------------------------------------------- | --------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
| `tcpdump` on the destination host shows nothing      | Inbound UDP dropped upstream by a security group, network ACL, or edge firewall   | Add an explicit inbound allow for the registered UDP port                                                  |
| `tcpdump` shows nothing and the host sits behind NAT | Unsolicited inbound UDP has no NAT state to match                                 | Move the receiver to a routable public IPv4 or a static one-to-one mapping                                 |
| `tcpdump` shows packets, the application sees none   | Socket bound to `127.0.0.1`, bound to the wrong port, or another process holds it | Bind `0.0.0.0` on the registered port; confirm with `ss -lunp`                                             |
| Traffic stopped after an infrastructure change       | The address or port moved; the registration still points at the old one           | Re-register the destination on [Discord](https://discord.gg/corvus-labs)                                   |
| `UdpRcvbufErrors` climbing under load                | Your receive buffer overflows before you drain it                                 | Raise `SO_RCVBUF`, move parsing off the read loop                                                          |
| `UdpNoPorts` climbing                                | Packets arrive while nothing is bound                                             | Keep the listener up; restarts lose everything sent meanwhile                                              |
| The same shred twice                                 | Expected; fire-and-forget delivery can duplicate                                  | Deduplicate in the receiver                                                                                |
| Shreds out of order, or gaps                         | Expected; UDP neither orders nor retransmits                                      | Order and gap-fill in the receiver; backfill from [JSON-RPC](/solana-rpc/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](/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](/platform/latency-stack) compares the two.

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

<Callout type="error" title="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](/solana-rpc) at the commitment level your application requires.
</Callout>

## Shredstream, Yellowstone gRPC or aRPC

| Need                                                                    | Use                                                               |
| ----------------------------------------------------------------------- | ----------------------------------------------------------------- |
| Filtered account, transaction, slot, or block updates on a typed stream | [Yellowstone gRPC](/solana-rpc/grpc), under Solana RPC (5 metros) |
| Pre-execution entry, transaction, and slot streams over gRPC            | [aRPC](/arpc) (9 metros)                                          |
| Native shred processing you implement yourself                          | Shredstream (9 metros)                                            |
