Turbine: Propagating Blocks as a Tree of Shreds
The previous page, Banking and PoH, left the leader holding something valuable: an ordered, executed, PoH-stamped block. The work of deciding what the block is, is done. Now comes a problem that sounds trivial and is not — the leader has to get that block into the hands of every other validator on the network, fast enough that the next leader can build on top of it a few hundred milliseconds later.
This page is about that hand-off. It builds on the throughline of the whole book — how do you build a single global state machine that runs at hardware speed without falling apart? — from a new angle: you can order and execute transactions at hardware speed all you like, but if you can’t distribute the result at hardware speed, the whole pipeline stalls behind the network card. Turbine is Solana’s answer.
The problem: one machine cannot feed a thousand mouths
Section titled “The problem: one machine cannot feed a thousand mouths”Start from first principles with the naive design and watch it break.
Say a leader produces a block of B bytes and there are N validators who need it. The obvious plan: the leader opens a connection to each of the N validators and sends all B bytes down each one.
The leader’s outbound network link is finite — call it U bytes/sec of upload. To send B bytes to N
peers, the leader must push B × N bytes through that one link. The time to do it is:
t_send = (B × N) / U
e.g. B = 128 MB block, N = 2,000 validators, U = 1 Gbit/s ≈ 125 MB/s
t_send = (128 MB × 2000) / 125 MB/s = 256,000 MB / 125 MB/s ≈ 2,048 seconds (~34 minutes)Thirty-four minutes to distribute one block, on a chain that wants a new block roughly every ~400 ms. The number is deliberately extreme, but the shape is the point: the naive cost grows linearly with the number of validators, and it is paid entirely by one machine. Adding validators — which is supposed to make the network more decentralized and robust — makes propagation worse. That is a scaling dead end. The leader’s single upload link is the bottleneck, and no amount of CPU or clever ordering upstream can fix a bottleneck that lives on the network card.
So the design question is sharp: how does a leader hand a large block to thousands of peers without its own bandwidth being the limit? The answer has two independent ideas — split the block up, and make the receivers do the relaying.
Shreds: a block is not sent, it is shredded
Section titled “Shreds: a block is not sent, it is shredded”The first idea: a block is never transmitted as one big object. Before anything leaves the leader, the block is chopped into small, fixed-ish-size pieces called shreds.
A shred is sized to fit comfortably inside a single network packet (on the order of a UDP datagram, low thousands of bytes). Each shred carries:
- a slice of the block’s serialized data,
- metadata: which slot and block it belongs to, and its index within the block,
- a signature from the leader, so a receiver can verify the shred is authentic and not injected by an attacker.
Why bother splitting at all? Three reasons, each a first-principles win:
- Packets are the unit the network actually moves. Sending one 128 MB “block” is a fiction — it is already going to be fragmented into thousands of packets by the transport layer. Shredding makes that explicit and controllable, so the protocol reasons in the same units the wire does.
- A lost packet costs a packet, not a block. If one shred is dropped, you have lost a few thousand bytes, not the whole block. This is what makes loss recoverable cheaply (next section).
- Shreds are independently routable. Once a block is a set of small, self-describing pieces, you can send different shreds down different paths — which is exactly what the tree needs.
┌───────────────── block (slot 42) ─────────────────┐ │ tx tx tx tx tx tx tx tx tx tx tx tx tx tx tx tx … │ └───────────────────────────────────────────────────┘ │ split ▼ [shred 0][shred 1][shred 2][shred 3] … [shred k-1] ← data shreds each ≈ one packet, signed by the leader, indexedHold onto the mental model: the leader no longer distributes a block; it distributes a stream of signed, indexed packets. Everything below is about routing those packets efficiently and surviving the ones that get lost.
The Turbine tree: make the receivers relay
Section titled “The Turbine tree: make the receivers relay”Here is the second idea, and it is the one that beats the linear bottleneck. Instead of the leader sending every shred to every validator, the leader sends each shred to only a small first layer of validators. Those validators relay it onward to a second layer, who relay to a third, and so on. The bandwidth cost of distribution is spread across the whole network instead of resting on one machine.
If you have used BitTorrent, this is the same instinct: a popular file is not served by one seeder pushing to everyone — every peer that receives a piece immediately becomes a source for that piece. Solana formalizes that into a fixed, deterministic broadcast tree called Turbine.
leader │ (sends each shred to the root layer) ┌────────────┼────────────┐ ▼ ▼ ▼ node A node B node C ← layer 1 (root / neighborhood) ┌──┼──┐ ┌──┼──┐ ┌──┼──┐ ▼ ▼ ▼ ▼ ▼ ▼ ▼ ▼ ▼ … … … … … … … … … ← layer 2 (and so on, deeper as N grows)Why a tree, and why fan-out shrinks the work
Section titled “Why a tree, and why fan-out shrinks the work”The magic of a tree is that depth grows logarithmically with the number of validators. If each node
relays to a fan-out of f children, then a tree can reach N validators in about log_f(N) layers:
layers ≈ ceil( log_f(N) )
e.g. f = 200 (fan-out), N = 2,000 validators layers ≈ ceil( log_200(2000) ) ≈ 2
Each validator's upload cost is now ~f shreds' worth per shred it relays, NOT N. The leader's cost drops from "send to N" to "send to one layer."The leader’s job collapses from “transmit the whole block N times” to “transmit each shred once, to a small root layer.” Every other byte of upload is contributed by validators who are, after all, sitting there wanting the block anyway. The total bytes moved across the network is similar, but it is paid by many links in parallel instead of one — and total time drops from linear to roughly logarithmic in N.
Stake-weighted, and deterministic
Section titled “Stake-weighted, and deterministic”Two details make Turbine safe rather than merely fast:
- Stake-weighted placement. The tree is not random. Validators with more stake are placed closer to the leader (higher in the tree). The logic: a high-stake validator has more economic skin in the game and, in practice, tends to run better-provisioned infrastructure, so you want the most important relayers to receive blocks earliest and with the fewest hops. A validator with 30% of stake failing to get a block matters far more than a dust-stake node, so the protocol prioritizes it.
- Deterministic construction. Every validator can compute the same tree for a given slot from public information (the set of validators, their stake, and a slot-derived seed). Nobody has to be told their position — each node derives its own parent and children. That means there is no coordinator to attack and no negotiation round-trip, which keeps the whole thing consistent with the pipeline’s “no conversations” philosophy you met in Gulf Stream.
Erasure coding: surviving loss without asking again
Section titled “Erasure coding: surviving loss without asking again”A tree spreads bandwidth, but it introduces a fragility: shreds travel over UDP-style, best-effort transport across many hops, and packets will be dropped. If a validator is missing even one data shred, it cannot reconstruct the block. The naive fix — “notice the gap, ask my parent to resend shred 37” — reintroduces exactly the round-trip conversations the design is trying to avoid, and at the scale of thousands of nodes losing thousands of packets, those retransmit requests would themselves become a flood.
Solana’s answer is erasure coding (specifically Reed–Solomon codes). The idea: alongside the k data shreds, the leader computes m extra coding (parity) shreds and sends those through the tree too. The mathematical property of a Reed–Solomon code is:
Any k of the k + m shreds are enough to reconstruct all k data shreds.
You do not need shred number 37 specifically. You need any k of the total k + m. If up to m shreds are lost anywhere along the way, the receiver recovers the block by solving the code locally — no request to anyone, no round-trip, no retransmit storm.
block ──► k data shreds d0 d1 d2 … d(k-1) + m coding shreds c0 c1 … c(m-1) ← Reed–Solomon parity
send all (k + m) through the Turbine tree │ ▼ receiver gets a lossy subset: d0 __ d2 d3 __ __ … c0 c1 __ (some data + some coding lost) │ ▼ as long as ≥ k shreds arrived: reconstruct d0 … d(k-1) locally, block recovered.This is the same trick RAID uses to survive a dead disk and that CDs use to survive a scratch: trade a
little redundant bandwidth up front for the ability to tolerate loss without a conversation. The
redundancy ratio m / (k + m) is a tuning knob — more parity buys more loss tolerance at the cost of more
bytes on the wire. Turbine picks a modest ratio, betting that most loss is a small fraction of packets.
Contrast with Bitcoin: flood the pond, or route the river
Section titled “Contrast with Bitcoin: flood the pond, or route the river”It is worth putting Turbine next to how Bitcoin propagates blocks — because the two chains made opposite choices, and each choice follows from what the chain optimizes for.
Bitcoin uses gossip flooding: when a node learns of a new block, it tells its handful of peers, who tell their peers, and the block ripples outward through the mesh until everyone has it. There is no tree, no assigned structure, no erasure coding — just neighbors telling neighbors.
Bitcoin (gossip flood) Solana (Turbine tree) ───────────────────── ───────────────────── unstructured peer mesh deterministic stake-weighted tree every node re-broadcasts each node relays to assigned children redundant (same block seen one structured pass + erasure parity from several peers) robust, self-healing, simple fast, bandwidth-efficient, higher upkeep tuned for ~10-minute blocks tuned for ~400 ms slotsWhy the difference? Because they optimize for different numbers. Bitcoin has ~10 minutes between blocks and prizes decentralization and robustness above all; a redundant, unstructured flood is slow but almost impossible to break, and ten minutes is an eternity — there is no throughput pressure to justify anything cleverer. Solana has a few hundred milliseconds and prizes throughput; it cannot afford redundant flooding, so it accepts a more complex, structured, loss-coded tree to move a much larger block in a much smaller window. Flooding is robust because it wastes bandwidth on purpose; Turbine is fast because it refuses to. Neither is “correct” — they are different points on the same trade-off surface you first saw in Day 26’s throughput problem.
Under the hood — Turbine sits between banking and validating
Section titled “Under the hood — Turbine sits between banking and validating”Turbine is one pipeline stage, not a standalone system. On the sending side it is the last stage of the leader’s work: the banking/PoH stage from the previous page hands finished entries to a broadcast service, which shreds them, computes coding shreds, and pushes them into the tree. On the receiving side, a validator’s networking layer collects incoming shreds, retires the coding shreds once enough have arrived, reassembles the block, and hands it to the next stage — the TVU, where the block is replayed and validated rather than merely received. Turbine’s single job is delivery; deciding whether the delivered block is any good is the TVU’s job, and the next page.
Note what Turbine deliberately does not do, so you don’t over-credit it: it is not consensus, it does not decide which fork wins, and it does not verify that the transactions inside the block are valid — it only verifies each shred’s leader signature to reject forgeries in transit. It is pure transport, optimized to the hilt.
The architect’s lens
Section titled “The architect’s lens”- Why does it exist? Because a leader’s single upload link cannot fan a large block out to thousands
of validators fast enough — naive one-to-many broadcast costs
O(N)on one machine, which is a scaling dead end at ~400 ms slots. Turbine exists to move that cost off the leader and onto the whole network. - What problem does it solve? Block distribution at high throughput: it turns a linear, single-link broadcast into a logarithmic-depth tree where every receiver also relays, and it turns packet loss into a locally-solvable math problem instead of a retransmission storm.
- What are the trade-offs? It buys speed and bandwidth efficiency with complexity and structure — a deterministic stake-weighted tree that every node must compute identically, plus redundant coding shreds that spend extra bandwidth for loss tolerance. It is less brute-force-robust than Bitcoin’s flood: a mis-placed or failing high-stake relayer can slow delivery to a whole subtree.
- When should I avoid it? When you are not bandwidth- or latency-bound. A chain with minutes between blocks (Bitcoin) gains nothing from a tree and is better served by simple, self-healing gossip. Turbine earns its complexity only under real throughput pressure.
- What breaks if I remove it? The pipeline stalls at the network card: blocks can be ordered and executed at hardware speed but not delivered in time, so the next leader has nothing solid to build on, confirmation latency balloons, and the “one fast synchronous L1” bet collapses regardless of how good the upstream stages are.
Check your understanding
Section titled “Check your understanding”- Walk through why the naive design — a leader sending the full block to each validator over its own link — does not scale. What quantity grows with the number of validators, and where is the bottleneck?
- What is a shred, and name two first-principles benefits of transmitting a block as many small signed shreds rather than one large object.
- Explain how the Turbine tree spreads bandwidth cost across the network, and why the number of layers grows only logarithmically with the validator count.
- Reed–Solomon coding lets a validator reconstruct a block “even though it never received shred 37.” Explain the property of the code that makes that true, and why it is better than asking a peer to resend the missing shred.
- Contrast Turbine with Bitcoin’s gossip flooding. What does each chain optimize for, and why does that goal make a structured tree right for Solana and a redundant flood right for Bitcoin?
Show answers
- The leader must push
B × Nbytes (block size × validators) through its single upload link U, so the send time(B × N) / Ugrows linearly with N and is paid entirely by one machine. Adding validators makes distribution slower, and no upstream CPU or ordering work can fix a bottleneck that lives on the leader’s network card. - A shred is a small, packet-sized, signed, indexed piece of a block. Benefits (any two): it matches the unit the network actually moves (packets); a lost shred costs a few thousand bytes rather than the whole block, making loss cheaply recoverable; and independently-routable shreds let different pieces travel different paths through the tree.
- The leader sends each shred to only a small first layer; those validators relay to the next layer,
and so on, so every receiver also contributes upload bandwidth instead of the leader alone. With a
fan-out of
f, a tree reaches N validators in aboutlog_f(N)layers — depth grows logarithmically because each layer multiplies reach byf, so total delivery time is roughly logarithmic in N rather than linear. - A Reed–Solomon group of
kdata +mcoding shreds can reconstruct all data from anykof thek + mshreds — you need k of anything, not shred 37 specifically. So up tomlosses are recovered by local arithmetic, with no round-trip. Retransmission instead sends a “resend” request back up the tree per missing shred per validator, which at scale becomes its own flood; coding replaces that back-channel entirely. - Bitcoin optimizes for decentralization and robustness with ~10-minute blocks, so an unstructured, redundant gossip flood — slow but nearly unbreakable and self-healing — is the right fit. Solana optimizes for throughput with ~400 ms slots, so it cannot afford redundant flooding and accepts a more complex, deterministic, stake-weighted tree plus erasure coding to move a much larger block in a much smaller window. Flooding is robust because it wastes bandwidth; Turbine is fast because it refuses to.