Background
A real client (5chan.app) cold-loads a whole directory: ~63 boards join at once, each firing one root-record fetch, landing as concurrent inbound streams on the shared seeder. libp2p 3.3.4 registers every protocol handler with DEFAULT_MAX_INBOUND_STREAMS = 32 (per connection, per protocol, per direction) and @libp2p/fetch passes no override — so a default node serves 32 and resets the rest (TooManyInboundProtocolStreamsError).
Correctness is already handled client-side (measured on the WAN rig, npm run bench:directory-load): no retry → 32/63 boards converge; the shipped retry-to-deadline (#fetchRootWithRetry) + the voter-wide 24-per-peer fetch budget + subscriber shuffling → 63/63 in ~6.3 s against a default-capped node.
The remaining item
Raising the cap on the seeder side is a worthwhile deployment improvement — it eliminates the reset/retry churn entirely (measured ~8.6 s naive all-at-once with zero resets; wall-clock comparable within WAN jitter, but no stream aborts, no retry storms, and headroom if directories grow or if same-connection non-library fetch traffic — e.g. the host's IPNS-over-pubsub record fetches — eats into the 32):
fetchService({ maxInboundStreams: 1024, maxOutboundStreams: 1024 })
(Helia's bitswap already defaults to 1024, so the checkpoint chase is not a wall; only the fetch handler's default matters. Reproduce with BENCH_FETCH_MAX_STREAMS on the directory bench.)
Action
Background
A real client (5chan.app) cold-loads a whole directory: ~63 boards join at once, each firing one root-record fetch, landing as concurrent inbound streams on the shared seeder. libp2p
3.3.4registers every protocol handler withDEFAULT_MAX_INBOUND_STREAMS = 32(per connection, per protocol, per direction) and@libp2p/fetchpasses no override — so a default node serves 32 and resets the rest (TooManyInboundProtocolStreamsError).Correctness is already handled client-side (measured on the WAN rig,
npm run bench:directory-load): no retry → 32/63 boards converge; the shipped retry-to-deadline (#fetchRootWithRetry) + the voter-wide 24-per-peer fetch budget + subscriber shuffling → 63/63 in ~6.3 s against a default-capped node.The remaining item
Raising the cap on the seeder side is a worthwhile deployment improvement — it eliminates the reset/retry churn entirely (measured ~8.6 s naive all-at-once with zero resets; wall-clock comparable within WAN jitter, but no stream aborts, no retry storms, and headroom if directories grow or if same-connection non-library fetch traffic — e.g. the host's IPNS-over-pubsub record fetches — eats into the 32):
(Helia's bitswap already defaults to 1024, so the checkpoint chase is not a wall; only the fetch handler's default matters. Reproduce with
BENCH_FETCH_MAX_STREAMSon the directory bench.)Action
dataPathrequirements (DESIGN.md "Deferred pkc-js work" already documents the details).