WebSocket to ShredStream: When Optimization Stops Helping

The Day Optimization Stopped Helping

I have been staring at the same dashboard for weeks. The bot detects opportunities, builds bundles, submits them — and lands almost nothing. Not zero in the literal sense, but close enough that the difference is statistical noise. The strategy is mathematically sound. The arbitrage paths are real. The bundles are well-formed. And the win rate refuses to move.

The instinct, when you have spent enough time inside a system, is to keep tuning. Shave a millisecond off transaction construction. Pre-warm the data parser. Skip a branch in the hot path. I have done all of that. The line on the chart did not care.

What I am only now starting to accept is that none of those optimizations matter, because the bot is reading data from the wrong place in the pipeline. Every millisecond I save in code is being canceled out by hundreds of milliseconds I am losing at the data layer. I am running a Honda Civic in a Formula 1 race and tuning the cup holders.

The Pipeline No One Drew For Me When I Started

When I first built the bot, I picked WebSocket because that is what every Solana tutorial uses. It is in the docs. It plugs into Node. It speaks JSON. It is the default. Like signing up for the basic cable package because the salesman didn't mention the sports tier exists.

What I did not understand, and what almost nobody mentions in introductory material, is that on Solana there are at least three distinct stages at which data becomes available to you, and each stage sits at a different distance from the block leader:

  1. Shred-level access. The block leader breaks transactions into shreds — small, signed packets — and starts propagating them the moment they exist. Subscribers who receive shreds directly are getting data essentially at the source.
  2. Validator-memory streaming (Geyser / gRPC). Once a validator has received and processed shreds, it can stream account and transaction updates from memory over a structured binary protocol.
  3. WebSocket from a standard RPC endpoint. The RPC node waits until the block is fully reassembled and committed, then serializes the result into JSON and ships it out over a WebSocket connection.

These are not interchangeable. They are layers, and the layer you subscribe to is upstream of every line of code you write afterward. An infrastructure provider puts it directly: "WebSockets deliver data post-shred reassembly, adding anywhere from 400ms to 30 seconds of latency" (source).

The Solana network produces a new block roughly every 400 milliseconds. If my data is showing up at the late edge of that window — or worse, well past it — I am not playing the same game as the bots living one layer deeper.

What A Shred Actually Is

For months I treated "the block" as the atomic thing. The block arrives, I react to the block. That mental model was the trap. The block is a finished product. What actually crosses the wire first is shreds.

A shred is roughly 1.2 KB, sized to fit inside a standard network MTU so it does not need to be fragmented in flight (source). The leader produces them, signs them, and immediately starts forwarding. The network then uses a propagation system called Turbine to fan them out: the leader hands shreds to a root layer, that layer forwards to the next, and so on. Fanout is large — on the order of 200 nodes per layer — and the whole tree typically spans only two or three hops.

Turbine is also stake-weighted. Validators with more stake tend to receive shreds in earlier layers. Validators with little or no stake sit at the tail of the fanout. That detail matters: if your RPC provider's node sits deep in the tree, you are inheriting that depth, plus the reassembly wait, plus the serialization step, plus the WebSocket round-trip.

I had been thinking of WebSocket as a transport choice. It is actually a position choice.

WebSocket Is Not Wrong. It Is Just Late.

I want to be careful here, because I have seen developers online treat "use WebSocket" as if it were a beginner mistake. It is not. WebSocket is a full-duplex, bidirectional protocol that runs over a single long-lived connection. It is supported in every browser, every major language, and every cloud platform. For wallets, dashboards, account watchers, low-volume bots, and basically anything where 200-millisecond freshness is acceptable, WebSocket is the right answer.

An analysis of Solana data streams calls WebSocket "a very rational choice for launching a product, especially from the frontend" (source). It plugs into normal web infrastructure. It is readable. You can debug it with the same tools you use for any HTTP-adjacent service.

The problem is that for the specific game I am trying to play — arbitrage on opportunities that exist for fractions of a slot — WebSocket has a structural ceiling. No amount of code cleverness on my end pulls data forward in the pipeline. It is, as the same analysis notes, the "heaviest" of the common Solana streaming options. Shred-level UDP is the "lightest and fastest." The order is fixed.

The analogy I keep coming back to: WebSocket is the morning newspaper. It is well-edited, easy to read, and arrives reliably. ShredStream is a police scanner. It is noisy, you have to decode it yourself, and it is happening live. You cannot beat the scanner to a scene with a newspaper, no matter how fast you read.

Where ShredStream Sits

The Jito ShredStream is, in plain terms, a service that forwards raw shreds from leaders directly to subscribers over UDP. It deliberately bypasses the standard Turbine fanout that the rest of the network uses for propagation. An infrastructure provider describes it as bypassing "Solana's standard Turbine protocol, which introduces variability through network hops and uneven validator proximity to block leaders" (source).

The official documentation for the Jito Block Engine lays out the mechanics fairly clearly. The default ingress port is 20000/udp. Each shred is about 1,200 bytes. There is an authentication keypair, a heartbeat loop to keep the stream live, and a set of geographic regions you can subscribe from. The protocol is, on the wire, exactly as plain as it sounds: signed UDP packets, arriving as fast as the leader can send them (source).

The payoff is positional. Where WebSocket sits at the end of a chain that runs Leader → Turbine fanout → RPC reassembly → JSON serialization → wire, ShredStream sits at Leader → UDP → you. Two of the most expensive stages — the multi-hop fanout and the JSON pipeline — are gone.

That is the whole insight, and once you see it, it is hard to unsee. The question stops being "how do I make my detection loop faster?" and becomes "what stage of the pipeline am I subscribed to?"

The Numbers, And Why I Trust Them Cautiously

There are public benchmarks for this, and I want to be honest about how much weight to give each one.

A benchmarking source published a comparison against Yellowstone gRPC across more than two million transactions, and reported that ShredStream delivered data first in 64.5% of cases, with an average advantage of 32.8 milliseconds (source). Against standard gossip-based propagation, the same source pegs the advantage at 50 to 200 milliseconds (source). A separate benchmarking source ran a controlled test on the same Solana node, ten-minute windows with ShredStream enabled and disabled, and reported 37% more slots inside the optimal timing window and roughly three times fewer missed slots when ShredStream was on (source).

These are vendor benchmarks. They are also benchmarks where the vendors have a commercial interest in the answer looking good. I take the directional claim — shred-level access is meaningfully ahead of validator-memory streaming, which is meaningfully ahead of WebSocket — as well established. I would not bet my house on the specific 32.8-millisecond figure being identical on my hardware in my region.

What I do trust, more than any individual measurement, is the underlying argument: if shreds are produced before they are reassembled, and reassembly is before JSON serialization, and JSON serialization is before WebSocket delivery, then on average each step costs time. The numbers are consistent with the physics.

The Market Around This

It is worth grounding why anyone is willing to invest in this complexity at all. One industry analysis pegs total Solana MEV revenue for full year 2025 around $720 million (source). The same source notes a single launch event in January 2025 where bots collectively paid more than 8,500 SOL in tips inside one hour. The Jito Block Engine pulled in millions in Q3 2025 fees alone, per the same source.

The relevant detail for someone in my position is not the absolute dollar number. It is the structure of competition the number describes. One analysis puts it cleanly: "Searchers must compete over latency rather than fees" and "being able to read state first means being the one to successfully execute a profitable trade" (source). In a winner-takes-all auction where the leaders pay a large share of their profits in tips, the marginal bot is the one who saw the opportunity slightly earlier and could submit slightly sooner.

When that is the game, being 200 milliseconds late is the same as being a week late. The opportunity is gone. The on-chain state has already updated. Someone else's bundle is already on the leader's desk.

This is what I now suspect was happening on my dashboard. The strategy was not broken. The pipeline was.

Why It Is Not A Drop-In Replacement

This is the part of the lesson I am bracing for. ShredStream is faster, but the price is a fundamentally different programming model. The same analysis of Solana data streams says it directly: shred-level streams "require you to design for missing and out-of-order data from the beginning" (source).

WebSocket gave me a finished, sequenced, JSON-decoded view of the world. ShredStream gives me a UDP firehose of signed packets that I have to reassemble, deduplicate, validate, and order myself. UDP does not guarantee delivery. UDP does not guarantee ordering. The protocol assumes I will handle both.

An analyst frames it well in his integration notes: "ShredStream provides ordered entries, not a queryable state" (source). It is not a database I can ask questions of. It is a real-time signal feed. If I need to look something up — historical balances, account state, anything that requires a query — I still need a normal indexed data source on the side. The two have different jobs.

The same notes list three failure patterns the author sees teams hit repeatedly: treating ShredStream as a database instead of a signal, sizing infrastructure for average load instead of peak load, and getting heartbeat management wrong. The warning on capacity has stuck with me: "latency and backlog grow exactly when the market is most profitable." When the network is on fire and you most want your bot to be working, that is when a system sized for averages quietly stalls. The recommendation is to size "for the worst 1 percent of slots." That is a different posture than "works on my machine."

This is engineering work I have not yet done. I have written WebSocket consumers, not packet-level reassemblers. The leap is real.

Working Harder Versus Doing It Differently

The deeper lesson — the one I think I will keep thinking about long after this specific migration is over — is the difference between optimizing inside a layer and changing layers.

For months, every fix I shipped was an in-layer optimization. Tighter loops. Smarter caching. Better path-finding. Lower allocation pressure. Each one was technically sound, and each one delivered a small, real win, and none of them moved the dashboard. That is because the layer I was in had a ceiling I could not see. From inside the layer, the ceiling felt like "I just need to try harder." From outside, it is obvious: the data is arriving too late, and faster code on stale data is still stale.

This is a familiar pattern from other industries. A retailer can optimize its checkout software for years and never close the gap with a competitor whose entire supply chain runs through a different distribution model. A small newspaper can hire faster reporters and still lose every breaking story to a wire service. A baseball team can squeeze every inch out of its scouting reports and still be outrun by a club that switched to a different player-development pipeline a decade earlier. The layer is the constraint. Tuning the inside of the wrong layer is a polished failure.

An article on the topic is uncharacteristically blunt: "Solana MEV infrastructure: why the stack matters more than the strategy" (source). I would have found that statement annoying six months ago. Today it reads like someone trying to save me time.

The Honest State Of My Bot

I am not switching to ShredStream this week. I am also not going to pretend the engineering cost is small. The transition is, in practical terms, a partial rewrite of the data path. UDP socket handling. Reassembly buffers. Deduplication logic. Backpressure. A separate path for querying historical state, because ShredStream cannot fill that role. Authentication and heartbeat plumbing. Region selection. Capacity planning for peak slots instead of average slots.

There is also a posture change I need to internalize. Inside the WebSocket world, I treat the feed as authoritative. The data is already cleaned up. Inside the shred world, the feed is a stream of signals that I am responsible for turning into a usable picture. The bot has to be skeptical of its own input in a way it never had to be before.

What I do not want to do is the worst version of this migration, which is to bolt ShredStream onto the side of the existing architecture and treat it like a faster WebSocket. That is the "treating it as a database" mistake the integration notes warn about. The shape of the system needs to change with the data source. A police scanner is not a faster newspaper. It is a different thing that you build a different newsroom around.

What I Think I Have Actually Learned

A few things are clearer to me now than they were last month.

The first is that latency in a competitive market is not a property of code. It is a property of position in the data pipeline. Optimizing within the wrong layer is a way of feeling productive without being productive. You can see your benchmarks improve and your outcomes not move, and that gap is the universe telling you the bottleneck is somewhere you are not looking.

The second is that the comfortable choice is almost always a layer too high. WebSocket is comfortable. JSON is comfortable. A fully-formed block is comfortable. Comfort, in this domain, is a tell. If the tooling makes the data nice for you, somebody is doing the niceness work, and that somebody is taking time you do not have.

The third is that switching layers costs real engineering and is not glamorous. It is not the same as inventing a new algorithm. It is reading UDP packets and writing reassembly code and arguing about backpressure. It is also, as far as I can tell from the experience of teams who have already done it, the only thing that actually changes the line on the dashboard.

I do not know yet whether my strategy will work once it sits on a faster pipeline. It is entirely possible the math has other problems, hidden behind the latency problem, that I have not yet been able to see. I will find out. But I no longer believe that more code optimization on the current data path is the answer. The ceiling is structural, and the way past a structural ceiling is to stand somewhere else.

Key Takeaways

  • On Solana, the data layer you subscribe to — shreds, validator memory, or WebSocket — sits upstream of every code optimization you can make. The layer is the constraint.
  • WebSocket is not a beginner mistake. It is the right tool for wallets, dashboards, and most consumer applications. It is the wrong tool for strategies competing inside a 400-millisecond slot window.
  • Public benchmarks from infrastructure vendors put ShredStream meaningfully ahead of validator-memory gRPC, which is meaningfully ahead of WebSocket. Treat the direction as solid and the specific numbers as situational.
  • ShredStream is harder to build against: UDP, reassembly, deduplication, separate state queries on the side, capacity sized for peak slots rather than average slots.
  • The deepest lesson is not about Solana. It is about the difference between optimizing inside a layer and changing layers. When the dashboard refuses to move despite real code wins, the bottleneck is probably one level up from where you are looking.

Disclaimer

This article is for informational and educational purposes only and does not constitute financial, investment, legal, or professional advice. Content is produced independently and supported by advertising revenue. While we strive for accuracy, this article may contain unintentional errors or outdated information. Readers should independently verify all facts and data before making decisions. Company names and trademarks are referenced for analysis purposes under fair use principles. Always consult qualified professionals before making financial or legal decisions.