Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Node Tuning for Block Latency

How fast your pool hands miners a job for a new block is decided almost entirely by Bitcoin Core, not by the pool. This page is the measured chain from “the network has a block” to “your miners work on it”, with the knobs that moved each link on our reference deployment (Hetzner, 4 vCPU, Core 31.1, IPC template source) and on an Umbrel Home at the other end of a consumer line. All numbers are medians over the blocks named; your node will differ, the ordering will not.

The chain, and where the milliseconds go

network block  →  node hears it  →  reconstructs it  →  validates it  →  template  →  job
                  (peers)           (compact block)     (UTXO cache)    (Core)       (pool)
LinkReference box, beforeafter tuningUmbrel Home
hears the block (vs. a fast relay pool’s job)+12 ms−17 ms−2 ms
compact-block reconstruction90–150 ms, every block60 ms, 10 of 36 blocks at ~2 ms97 ms
validation80–100 ms98 ms38 ms
Core builds the template35–40 ms35–40 ms—
pool fetches the template over IPC~18 ms~18 ms—
pool maps the template and builds the job~48 ms~33 ms (parallel mapping, v1.26.0)—

“Before” was a stock bitcoind with 125 peers; “after” is the configuration below. The pool side (last two rows) is the same code on both machines; see Performance Benchmarks for how it is measured.

Peering: hear the block early

A node with only default outbound peers hears a block one or two gossip hops after the fast relay networks. Two things closed that gap for us:

  • Inbound connections. Open 8333/tcp on your router and set listen=1. A node with 100+ inbound peers hears blocks from whichever of them got it first. The setup wizard flags a node without inbound peers.
  • A manual peer that sits on a relay network. addnode=<host> to a node you trust to be fast — other pools are the obvious candidates, and several operators publish their node addresses for exactly this purpose. It is trustless: your node validates every block anyway; the peer only shortens the path. Adding one such peer took the reference box from hearing blocks 12 ms after a relay-connected pool’s job went out to 17 ms before.

Our own node accepts peers at 91.98.76.244:8333 (Nuremberg, Core 31.1).

Reconstruction: avoid the round trip

Compact blocks (BIP 152) carry short transaction IDs; the node rebuilds the block from its mempool and asks the peer only for what it lacks. That request is one round trip — 90–150 ms in a data centre, more from home — and it happened on every block on the stock configuration.

# bitcoin.conf
blockreconstructionextratxn=1000

The “extra pool” keeps recently rejected, replaced or orphaned transactions that are not in the mempool but often are in the next block. The default is 100; at 1000 the reference box reconstructed 10 of 36 blocks with no round trip at all (0–3 ms), and the median dropped from 90–150 ms to 60 ms. The cost is a few megabytes of RAM. The wizard’s bitcoin.conf snippet recommends this key when it is absent.

Blocks that still need the round trip contain transactions no node on your side of the network had seen — a large mempool (maxmempool) and many peers help a little, no setting removes it.

Validation: keep the UTXO set in RAM

Connecting a block means looking up every input. With the UTXO cache warm that is ~40 ms on an Umbrel Home (dbcache=4000) and ~100 ms on the reference box (dbcache=1500, 2 GHz vCPUs). Raise dbcache as far as RAM allows once the node has settled — and note the price of every restart below.

What a node restart costs

Every bitcoind restart we measured cost the same two things:

  • The first block after the restart validates cold: 3.6 s instead of 0.1 s, three restarts out of three. The UTXO cache is empty and every input is read from disk.
  • Peers come back slowly. Outbound refills in a minute; inbound takes hours. Until then the node hears blocks later and its mempool coverage is thinner, so more blocks need the reconstruction round trip.

So bundle configuration changes into one restart, and do not restart a production node to save 50 ms.

Measuring it yourself

Two things make the chain visible on any node:

# bitcoin.conf — microsecond timestamps and one log line per compact block
logtimemicros=1
debug=cmpctblock

debug.log then shows, per block, Initialized PartiallyDownloadedBlock (the node heard it), Successfully reconstructed block … and N txn requested (N = 0 means no round trip) and UpdateTip (validated). The ipc-latency-probe binary from the warppool-bitcoin-ipc crate runs beside the pool and splits the pool’s own share into waitNext, the IPC fetch and the mapping step. Both logging switches can be toggled at runtime with bitcoin-cli logging; only logtimemicros needs a restart.

What is not worth it

A private block-relay network of your own (FIBRE-style edge listeners forwarding to your node) removes at most the reconstruction round trip once the peering above is in place — 60 ms, or 0.01 % of a block interval — for thousands of lines of code and a fleet of VPSs. Peer with one instead.