ArchiveAILEENA MACHINA
ENGINEERING PRIMER2026.05.20Solana · Wire · Validator · gRPC · Shreds

The Wire
How Solana Actually Moves Bytes

Everything that happens between your getAccountInfo call and the bytes coming back. Slots, shreds, turbine, leader schedule, RPC nodes, commitment levels, forks, ShredStream — and why none of it is quite what the documentation makes it sound like. A field guide to the layer below the API.

01 — The Useful Lie of getAccountInfo

You write connection.getAccountInfo(pubkey). A promise resolves with the account state. The code reads like the connection is a database query and the network is invisible. It is not. Between those two lines of code, your request leaves your process, crosses three or four networks, enters a validator that is replaying the entire chain in lockstep with the leader, snapshots a 165-byte slice of memory, encodes it as base64, wraps it in a JSON envelope, and sends it back. The latency floor on that round trip — 50 to 200 milliseconds against a serious provider — is set by physics, by the JSON parser, and by how recently the validator finished applying the last slot.

The documentation makes this look like a function call. It is a network journey. The rest of this article walks the journey, top to bottom: how a block is built, how it propagates as shreds through the turbine tree, how the RPC node serves it to you, how the three call styles (JSON-RPC, WebSocket, gRPC) compare, and what the commitment-level dial actually controls. The goal is the mental model you need to debug a stuck transaction, choose a provider, or read a Yellowstone stream without flinching.

02 — Slots, Blocks, and the 400ms Heartbeat

Solana's clock is the slot. A slot is a 400-millisecond time bucket. The validator scheduled as leader for that slot tries to produce a block; if it succeeds, the slot has a block, if it fails or runs out of time, the slot is empty ("skipped"). Block height — the count of slots that produced actual blocks — therefore advances more slowly than slot height. At today's network conditions the network averages around 380–420ms per slot and skips roughly 5–10% of them under congestion.

A block is not a single object that gets sent. It is a sequence of entries — micro-batches of transactions interleaved with proof-of-history hashes. Entries exist for two reasons: they let the leader hash-stamp the passage of time deterministically (the PoH chain), and they let downstream validators execute non-conflicting transactions in parallel. Each entry contains a list of transactions, and each transaction contains one or more instructions, each targeting a specific program. From outside, the developer sees "a block of transactions." From inside the validator, it is a stream of entries threading through a parallel execution engine.

03 — The Shred: Solana's Sub-Block Unit

A block is not transmitted as a single object either. The leader breaks it into shreds — ~1,228-byte fragments — and broadcasts them the instant they are serialized, before the block is complete. There are two kinds. Data shreds carry the actual entry bytes. Coding shreds are Reed-Solomon parity fragments that let downstream validators reconstruct missing data shreds without re-requesting them. Together they form an FEC (forward error correction) set. A block with 1,000 transactions might serialize to ~150 data shreds plus ~50 coding shreds; lose any 50 of the 200 and the block is still recoverable.

The reason shreds exist as a primitive is propagation. If a block had to be transmitted atomically, the worst-case latency would be (block size / bandwidth) before a single downstream validator could start processing. By streaming shreds as they are produced, propagation overlaps with construction. By the time the leader finishes the last shred of slot N, downstream validators have already received and partially executed the first 80% of it. This is the reason Solana can target 400ms slots at all.

04 — Turbine: How Shreds Reach Every Validator

The leader does not broadcast every shred to every validator. That would scale O(N²) and saturate the leader's uplink. Instead, the leader picks a fanout of K direct neighbors (currently around 200), each of whom forwards to the next layer of K, and so on. The result is a tree of depth O(log N) — every validator in the cluster receives every shred in 2 or 3 network hops. This is Turbine.

               LEADER
                 |
       +---------+---------+
       |         |         |     <- depth 1: ~200 neighbors
      V1        V2  ...   V200
     /  \      /  \
    V   V    V   V              <- depth 2: ~40,000 forwards
   ...     ...     ...           <- depth 3: every remaining validator

The validator's position in this tree determines how soon it sees a shred. A validator at depth 1 sees shreds milliseconds before a validator at depth 3. This is the entire physics of the "low latency Solana node" product category. Co-located dedicated nodes (Triton Professional Trading Centers) pay to sit near the top of the tree. ShredStream operators (Jito) pay to receive shreds at the same depth as a validator without being one. There is no software trick that beats this — only network position.

The Reed-Solomon coding shreds matter here too. Without them, a dropped data shred would require a re-request, doubling the worst-case latency. With them, the receiving validator reconstructs the missing piece locally from whatever subset of the FEC set it has. Propagation is robust to packet loss without round trips.

05 — The Leader Schedule

Who is leader at any given slot is not random. The leader schedule is deterministic and published one full epoch — 432,000 slots, about two days — in advance. Each leader is assigned a 4-slot consecutive window (1.6 seconds of block production), then hands off to the next leader in the schedule. You can query getLeaderSchedule from any RPC and know exactly who will be leader at every future slot in the current and next epoch.

This determinism is what MEV searchers exploit. They do not send their transactions to the public mempool. They send to the TPU (Transaction Processing Unit, the QUIC endpoint a leader runs to receive transactions) of the next four scheduled leaders simultaneously, so whichever one becomes the active leader can pick the transaction up immediately. This is also what enables "cancel races" — a market maker can pre-position cancel transactions at the next four leaders so they land in the same slot as a competitor's incoming order.

06 — The Transaction's Journey

A transaction's lifecycle, end to end, has more steps than most documentation admits. The version below is the unabridged one.

1. Client signs. Your wallet or program builds a transaction (one or more instructions, a recent blockhash, a fee payer), signs it with the relevant private keys, and serializes it to binary.

2. Submit to RPC. The client calls sendTransaction on an RPC endpoint. The RPC forwards to the TPU of the current leader and the next few scheduled leaders. Under congestion this is where vanilla sendTransaction fails silently — drops, throttles, or never reaches a leader in time.

3. Leader includes it. The current leader receives the transaction, runs it through its banking stage, and includes it in an entry if it passes (signature valid, fee paid, account locks compatible with other transactions in the entry). Higher priority-fee transactions get included ahead of lower ones.

4. Shred propagates. The entry containing your transaction is packed into shreds and broadcast through turbine. Validators across the network receive, reconstruct, and replay.

5. Validators vote. Each validator votes on the block as part of its own block-production cycle (votes are themselves transactions, which is why ~85% of mainnet traffic is votes). When stake exceeding two-thirds has voted on the block, the slot reaches confirmed commitment — typically 400ms to 1 second after submission.

6. Finalization. 31+ slot lockouts after the vote, the slot reaches finalized commitment — about 12 to 15 seconds after submission. At this point the transaction is permanent; no fork can revert it.

The numbers worth memorizing: ~400ms to confirmed, ~13s to finalized. Everything "fast" — Jito bundles, Helius Sender, Triton Cascade — is about reducing the variance at step 2 (getting your transaction in front of the leader reliably). Nothing reduces step 5 or step 6 — those are consensus, not networking.

07 — The RPC Node: A Validator That Doesn't Vote

A Solana RPC node is not separate software. It is the same agave validator binary, started with --full-rpc-api and (usually) --no-voting. It receives shreds through turbine like any other validator, reconstructs blocks, replays every transaction, holds the full set of accounts in memory, and exposes the JSON-RPC server. The reason it exists at all is that ordinary validators do not expose getAccountInfo to the public — they are too busy doing consensus to serve thousands of read queries.

This architecture has a consequence developers feel directly: the read path inherits every constraint of the write path. The RPC node uses the same heavy memory footprint, the same expensive disk layout, the same tight coupling to the leader's tick rate. It is also why public RPCs throttle aggressively (a runaway dashboard could starve a real validator's replay) and why dedicated nodes cost thousands per month (you are renting a full validator's worth of resources just for reads). The 2026 architectural fight in RPC is whether this coupling should exist at all — projects like FluxRPC are betting it should not.

08 — JSON-RPC: The Polling Interface

The default way to talk to Solana is JSON-RPC over HTTP. POST a JSON envelope, get a JSON envelope back. The protocol has four fields: jsonrpc (always "2.0"), id (yours to echo), method (the call), params (a positional array). The response always carries either result or error.

curl https://api.mainnet-beta.solana.com -X POST \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc":"2.0","id":1,"method":"getAccountInfo",
    "params":["So11111111111111111111111111111111111111112",
              {"encoding":"base64","commitment":"confirmed"}]
  }'

The Solana-specific detail is params[1], the options object. encoding picks the format of any account-data bytes (base58, base64, base64+zstd, or jsonParsed for programs the RPC knows how to decode). commitment picks how settled the data must be (processed, confirmed, finalized). Method-specific filters live here too — getProgramAccounts takes filters: [{memcmp: {offset: 0, bytes: "..."}}] to push filtering server-side so you don't pay for irrelevant accounts.

The limitation of JSON-RPC is mechanical: each call costs one HTTP request, one TCP round-trip (three for cold TLS), and one JSON parse on each side. The protocol is pull-only — if you want to know when an account changes, you have to ask again. For a dashboard that polls every 5 seconds this is fine. For a market maker that needs sub-second reaction it is fatal.

09 — WebSocket Subscriptions: Push, Not Poll

Solana's WebSocket interface speaks the same JSON-RPC envelope but over a persistent connection, with the server pushing updates when state changes. The subscription methods mirror the read methods: accountSubscribe, programSubscribe, logsSubscribe, signatureSubscribe, slotSubscribe.

const ws = new WebSocket("wss://api.mainnet-beta.solana.com");
ws.onopen = () => ws.send(JSON.stringify({
  jsonrpc: "2.0", id: 1, method: "accountSubscribe",
  params: ["7XSQ...", {encoding: "jsonParsed", commitment: "confirmed"}]
}));
ws.onmessage = e => {
  const msg = JSON.parse(e.data);
  if (msg.result !== undefined) console.log("sub id:", msg.result);
  else handleNotification(msg.params);
};

Two response shapes come back. First, the subscription confirmation: {"result": 12345, "id": 1} — that integer is your subscription handle, which you pass to accountUnsubscribe when done. Then, every time the account changes, a push: {"method": "accountNotification", "params": {"subscription": 12345, "result": {...account...}}}.

Why this is faster than polling is mechanical: zero per-update round trips, no rate-limit budget burned re-asking the same question, latency drops to leader-to-you propagation time (~400ms at confirmed) instead of leader-to-you-plus-your-poll-interval. What it does not solve is the JSON parse cost — each notification still gets fully decoded — and the WebSocket framing overhead. That is what gRPC is for.

10 — gRPC / Yellowstone: The Binary Stream

gRPC swaps JSON for binary protobuf and HTTP/1 for HTTP/2 streams. The wire is unreadable to a human and unparseable to a curl command — you need a client generated from a .proto file. The standard Solana streaming interface is Yellowstone, originally authored by Triton and adopted by every serious provider. Its Geyser.Subscribe service takes a request describing which accounts, programs, transactions, slots, blocks, and entries you want, and returns a bidirectional stream of binary updates.

// Helius LaserStream — drop-in Yellowstone gRPC with replay
import { LaserstreamClient, CommitmentLevel } from "@helius/laserstream";
const client = new LaserstreamClient({ endpoint, apiKey });
const stream = client.subscribe({
  slots:        { all: {} },
  accounts:     { mine: { owner: ["TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"] }},
  transactions: { non_vote: { vote: false, failed: false } },
  blocksMeta:   { headers: {} },
  commitment:   CommitmentLevel.PROCESSED
});
for await (const update of stream) {
  if (update.account)     handleAccount(update.account);
  if (update.transaction) handleTx(update.transaction);
  if (update.slot)        handleSlot(update.slot);
}

Why this is the fastest network call available. Three reasons stack. (a) Binary protobuf, not JSON. The same account update is roughly 200 bytes over Yellowstone versus 600 bytes over JSON-RPC, before any compression. (b) HTTP/2 multiplexing. Many subscriptions ride one TCP/TLS connection — WSS gives you that, raw HTTP JSON-RPC does not. (c) Off-thread decoding. The Helius LaserStream JS SDK is the canonical example: the streaming engine, protobuf serialization, and slot tracking are all written in Rust; only application logic runs in JavaScript. NAPI bindings move data zero-copy. Throughput is ~1.3 GB/s sustained versus ~30 MB/s for a pure-JS Yellowstone client — about 40 times faster, because the JS event loop is no longer in the hot path.

The same stream interface is also where reliability features live. LaserStream tracks the last slot it acknowledged and asks the server to resume from that point on reconnect, recovering up to 24 hours of missed data. Triton's Dragon's Mouth ships the same underlying protocol. Both compress on the wire with Zstd (70–80% bandwidth reduction), which directly cuts the streaming-traffic cost.

11 — Commitment Levels: When the Data Is Real

Every Solana read takes a commitment level. The three values map to three points in the consensus lifecycle of a slot:

LevelWhat it meansTypical latencyRisk
processedLeader produced the block; not yet voted on~100–200 msCan be reverted if fork is abandoned
confirmedSupermajority of stake voted for the block~400 ms – 1 sEffectively final, ~0 reversion in practice
finalized31+ lockout slots past the vote~12–15 sMathematically irreversible

The trade-off is speed vs. certainty. A market maker uses processed on reads because 12 seconds of latency to finalized is fatal in a quoting loop. A wallet showing "your transfer succeeded" uses confirmed because that's the threshold where the user has near-certainty. An exchange crediting a deposit waits for finalized because the cost of crediting a reverted deposit is much higher than 13 seconds of latency.

The non-obvious thing: at the Yellowstone gRPC level, the server can buffer updates per slot at confirmed and finalized levels — it holds the update until the slot reaches that threshold, then releases. The Triton-recommended optimization is to subscribe at processed and do the buffering client-side: you get the lowest latency for time-sensitive code paths and keep control over how forks are handled.

12 — Forks: The Bug Most Devs Never See Until Production

Solana has forks. The chain is not a single chain in real time; at any given moment there are short-lived alternative branches that have not yet been resolved. A slot that looks live at processed can disappear if the network chooses a different fork. The slot doesn't just "not finalize" — it transitions to SLOT_DEAD, and every transaction it contained is gone. Never happened. Never charged. Never landed.

The Yellowstone slots subscription is how you become fork-aware. It emits a status for every slot the validator has seen: SLOT_FIRST_SHRED_RECEIVED (first shred arrived), SLOT_CREATED_BANK (execution bank instantiated), SLOT_COMPLETED (all shreds received, bank fully built), then eventually SLOT_DEAD or finalized. Fork-aware code buffers account updates by slot and releases them only when the slot reaches the commitment level the application requires. Code that doesn't do this works in development and breaks under production volatility — the failure mode is "the database says the trade happened but it didn't," and it's extraordinarily hard to debug if you weren't expecting it.

13 — Pre-Block Reads: ShredStream and the In-Flight Network

Everything above is about reading the network after a block is built. There is a deeper layer. A transaction sits in a shred for some number of milliseconds before that shred is bundled into a complete block; if you can read shreds as they propagate, you see the transaction before it is officially in a block. This is what Jito ShredStream does. It taps the turbine gossip layer, receives shreds as a validator would, reconstructs transactions from the data + coding shreds, and exposes them as a stream to its subscribers.

The window this opens is roughly 50 to 100 milliseconds — the time between a transaction being broadcast by the leader and the corresponding block being finalized at confirmed. The pump.fun cancel race lives in this window: a sniper bot sees an incoming buy on ShredStream, races a cancel-or-flip transaction through Jito bundles to the next leader before the original transaction reaches confirmed. You do not get execution metadata from a shred-level read (no logs, no status, no compute units consumed) — you get the raw transaction, ahead of consensus.

The validator client itself is being optimized at this layer too. Agave PR #12428, merged 2026-05-20, modifies the broadcast stage so the next scheduled leader is unconditionally included in shred broadcast targets — trimming the leader-to-leader handoff window. The implication: every cancel-race benchmark from 2025 was measured against a network with a slower handoff. Post-12428 mainnet is incrementally faster at this layer.

14 — Writing Back: sendTransaction, TPU, Bundles, SWQoS

Reading is the easy half. Writing — getting a transaction to actually land in a block during congestion — is where most production Solana code spends its scar tissue. Vanilla sendTransaction goes through the RPC, which forwards via UDP/QUIC to the TPU (Transaction Processing Unit, the QUIC endpoint a leader runs to receive transactions). Under congestion, the TPU's queue is bounded and the leader rejects whatever doesn't fit. The transaction silently drops.

The four production answers, in increasing order of sophistication and cost. Priority fees — add a ComputeBudgetProgram.setComputeUnitPrice instruction, pay extra micro-lamports per CU, and the leader prioritizes you in the inclusion queue. Jito bundles — submit your transaction as an atomic group through Jito's block engine, attach a tip to a validator, and the validator includes the bundle in exchange for the tip (also enables atomic multi-transaction execution, the foundation of MEV protection). Helius Sender — Helius's managed landing service: they multi-route through priority fees, Jito tip accounts, and their own staked validator paths, surfacing one endpoint that "just lands." Triton Cascade — a marketplace where validators sell stake-weighted QoS bandwidth (0.1 SOL per epoch per 100 PPS), buying guaranteed leader-side inclusion bandwidth rather than fighting the public mempool.

The reason any of this exists: SWQoS itself. Solana's leader allocates inclusion bandwidth in proportion to staked SOL — validators with more stake get priority forwarding of transactions, regardless of priority fee. If your transactions arrive via a high-stake validator's connection, they land. If they arrive via a low-stake or unstaked endpoint, they wait. Cascade monetizes this: validators sell access to their stake-weighted bandwidth, applications buy a reliable inclusion path. It is the only one of the four answers that operates at the consensus-level QoS layer rather than the fee market.

15 — The Mental Model

The whole stack, top to bottom: validators run consensus, broadcasting shreds through Turbine to every other validator in 2-3 hops. Shreds reconstruct into blocks; blocks belong to slots; slots progress from processed to confirmed to finalized. An RPC node is a validator that happens to expose a JSON-RPC server. The three call styles — JSON-RPC, WebSocket, gRPC — differ by polling vs. push, by JSON vs. protobuf, and by how much of the parsing the SDK can move off your application thread.

Every "fast" story in the Solana infrastructure landscape is a story about skipping a layer. Jito ShredStream skips the block-construction wait by reading shreds. Triton co-location skips depth in the turbine tree by sitting at depth 1. LaserStream SDKs skip the JS event loop by doing protobuf work in Rust. Lantern skips the network entirely by caching account state in a local sidecar process. Priority fees, Jito bundles, Helius Sender, and Cascade all skip the contested public TPU queue by buying inclusion bandwidth a different way.

Every "fast" product in Solana infrastructure is selling a way to skip a layer that the documentation pretends is invisible.

What the API documentation describes — getAccountInfo, sendTransaction, accountSubscribe — is the application surface. What actually happens is a four-layer journey through validators, shreds, the leader schedule, and consensus. You can ship code without knowing any of this. But the moment something doesn't work — a transaction that won't land, an account update that's 12 seconds late, a market maker whose cancels keep losing the race — every layer matters. The companion piece, The RPC Layer That Cut the Cord, takes the same machinery and reads it as a market: who sells what, and why.

The API is the function call.
The wire is the journey.

— AILEENA MACHINA / 2026

References

  1. Solana Docs — Cluster architecture & Turbine
  2. Solana Docs — Transactions and instructions
  3. Solana Docs — Commitment status
  4. Solana Docs — JSON-RPC API methods
  5. Solana Docs — WebSocket subscriptions
  6. Anza Agave (validator client) — GitHub
  7. Agave PR #12428 — send shred to next leader (merged 2026-05-20)
  8. Yellowstone gRPC — Dragon's Mouth source
  9. Triton Docs — Dragon's Mouth subscription types & payload shapes
  10. Helius — Introducing LaserStream
  11. Helius — LaserStream SDKs (JS/Rust/Go, 40× throughput, slot replay)
  12. Jito ShredStream Proxy — GitHub
  13. Jito Low-Latency Transaction Send & Bundles (docs)
  14. Solana Stake-Weighted QoS — overview
  15. Companion piece — The RPC Layer That Cut the Cord
← Back to Archive