Shreds

Solana ShredStream Setup Guide: Stream Raw Shreds in 15 Minutes (2026)

July 7, 2026AllenHark Team

ShredStream is the fastest way to read Solana: instead of waiting for a block to be assembled, propagated, and served over RPC, you ingest the raw shreds — the packets validators exchange while the block is still being produced. Done right, your system sees transactions milliseconds before anything downstream of an RPC blockSubscribe does.

This guide takes you from zero to a working shred feed. If you want the conceptual background first, read What Are Solana Shreds? — this post is purely practical.

Step 1: Pick your delivery mode

AllenHark ShredStream ships in two flavors, and the right one depends on how much latency you're actually paying for elsewhere:

Shared gRPCDirect UDP
How it worksWe verify and parse shreds, stream structured entries to you over gRPCRaw UDP packets forwarded from our validator nodes straight to your server's IP
LatencyReal-time + microseconds of parsingFastest possible — zero-copy forwarding
Integration effortLow — a gRPC subscriptionHigher — you parse shreds yourself
Best forMonitoring, standard bots, testing the edgeHFT, snipers, systems where every microsecond is P&L
Pricing$10/day · $59/week · $199/month$199/month · dedicated cluster 5 SOL/month

Two rules of thumb. First, start with shared gRPC — the daily pass exists precisely so you can test the edge cheaply before committing. Second, direct UDP only pays off if your server is network-close to the source: if you're streaming across an ocean, the transit time swamps the parsing time you saved. That's what Frankfurt co-location is for.

Step 2: Get an API key

  1. Log in to the AllenHark Console
  2. Open ShredStream and choose a pass (daily/weekly/monthly)
  3. Copy your API key — it's sent as an x-api-key header on every connection

Step 3: Connect (shared gRPC)

The shared feed speaks the standard shredstream-proxy protocol on 84.32.223.83:9090.

Rust

use tonic::{Request, transport::Channel, metadata::MetadataValue};
use shredstream_proxy_client::ShredstreamProxyClient;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let channel = Channel::from_static("http://84.32.223.83:9090")
        .connect()
        .await?;
    let mut client = ShredstreamProxyClient::new(channel);

    let mut request = Request::new(SubscribeEntriesRequest {});
    let api_key = MetadataValue::from_str("YOUR_API_KEY")?;
    request.metadata_mut().insert("x-api-key", api_key);

    let mut stream = client.subscribe_entries(request).await?.into_inner();

    while let Some(entry) = stream.message().await? {
        println!("slot={} entries={} bytes", entry.slot, entry.data.len());
        // entry.data contains serialized Entry structs: deserialize with
        // bincode into Vec<solana_entry::entry::Entry> to get transactions.
    }
    Ok(())
}

TypeScript

import * as grpc from "@grpc/grpc-js";
import * as protoLoader from "@grpc/proto-loader";

// shredstream.proto is published at https://allenhark.com/shredstream.proto
const def = protoLoader.loadSync("shredstream.proto");
const proto = grpc.loadPackageDefinition(def) as any;

const client = new proto.shredstream.ShredstreamProxy(
    "84.32.223.83:9090",
    grpc.credentials.createInsecure()
);

const metadata = new grpc.Metadata();
metadata.set("x-api-key", process.env.ALLENHARK_API_KEY!);

const stream = client.SubscribeEntries({}, metadata);
stream.on("data", (entry: { slot: number; data: Buffer }) => {
    console.log(`slot=${entry.slot} ${entry.data.length} bytes`);
});
stream.on("error", (err: Error) => {
    console.error("stream error, reconnecting:", err.message);
    // production systems: reconnect with backoff here
});

The proto file is served from allenhark.com/shredstream.proto.

Step 4: Parse entries into transactions

Each message's data field is a bincode-serialized vector of Solana Entry structs. In Rust:

let entries: Vec<solana_entry::entry::Entry> =
    bincode::deserialize(&entry.data)?;

for e in entries {
    for tx in e.transactions {
        // VersionedTransaction — filter by program ID, account keys, etc.
    }
}

Filter as early as possible. A busy slot carries thousands of transactions; if you only care about one program (a DEX, pump.fun, a specific pool), drop everything else before it touches your strategy code. For a worked example of program-level filtering for launch sniping, see Best Shreds Setup for Pump.fun.

Step 5 (optional): Go direct UDP

When you've validated the edge and want the parsing time back:

  1. Provision a server with a static IP — ideally in the same facility as the source (Frankfurt bare metal is the canonical choice)
  2. Give us the IP; we whitelist it and forward raw UDP shreds to your port
  3. Ingest with the jito-shredstream-proxy tooling or your own deshredder

You take over verification and reassembly — that's the deal: UDP gives you speed, you supply the reliability.

Common pitfalls

  • Streaming across the Atlantic and wondering where the edge went. Shreds beat RPC by milliseconds; a 90ms transit eats that many times over. Co-locate or pick the nearest region.
  • No reconnect logic. gRPC streams drop — network blips, deploys. Reconnect with exponential backoff and expect to miss a slot or two; design the strategy to tolerate it.
  • Parsing everything. Deserialize, filter by program ID, then process. The other order melts CPUs on busy slots.
  • Treating shreds as confirmed data. You're seeing block production, ahead of consensus. A slot can be skipped. Act on shreds, confirm on commitment levels.

Where ShredStream fits in the stack

Shreds are the read side. If the goal is end-to-end speed you also need the write side: Slipstream for 0-slot transaction landing and Jito bundles when execution must be atomic. The full comparison of read paths — shreds vs gRPC vs RPC vs WebSockets — covers when each is the right tool.

Questions, or want the dedicated cluster? Join the Discord or head to the console and start with a $10 day pass.