This page is a live snapshot of how syncing is performing on this daemon.
The two tails worth watching most:
connected_sync p99 in Discovery latency — what the user feels when clicking a document.bitswap_fetch in Sync-with-peer latency — usually the dominant wall-clock per peer.| phase | p10 | p50 | p90 | p99 | count |
|---|---|---|---|---|---|
| peer_select | 31ms | 134ms | 357ms | 703ms | 208 |
| connected_sync | 455ms | 1.61s | 3.30s | 13.06s | 89 |
| dht_discover | 100µs | 500µs | 900µs | 990µs | 64 |
| dht_sync | — | — | — | — | 0 |
| total observations: 361 | |||||
| outcome | p10 | p50 | p90 | p99 | count |
|---|---|---|---|---|---|
| connected | 2.07s | 2.94s | 5.09s | 9.45s | 25 |
| dht | — | — | — | — | 0 |
| notfound | 874ms | 1.76s | 2.93s | 14.01s | 64 |
| error | 22ms | 95ms | 178ms | 668ms | 113 |
| total observations: 202 | |||||
| phase | p10 | p50 | p90 | p99 | count |
|---|---|---|---|---|---|
| dial | 126µs | 630µs | 2ms | 298ms | 550 |
| reconcile_rpc | 22ms | 94ms | 1.79s | 3.23s | 467 |
| bitswap_fetch | — | — | — | — | 0 |
| putmany | — | — | — | — | 0 |
| total observations: 1035 | |||||
For each individual peer in a sync, four phases run in order:
| outcome | count |
|---|
How each bitswap download loop terminated. One increment per fetch.
| outcome | p10 | p50 | p90 | p99 | count |
|---|
Same per-call timing as the bitswap_fetch row above, but split by termination reason. Watch the complete row's p90/p99 — that's "real fetches, how long do they take" without the timeout cases skewing the picture.
| outcome | p10 | p50 | p90 | p99 | count |
|---|
For each fetch: time between the LAST block received and the moment the download loop exited. Tells us what each outcome actually means in practice.
Per fetch: downloaded ÷ wanted. A row at ≤ 1.00 with most of the count means we got every blob asked for. Counts in lower buckets mean blobs are missing — either gateways don't have them or bitswap couldn't find them within the idle window. mean=1.00 healthy; mean=0.85 means we lose ~15% of asked-for blobs on average.
| <= wants | count |
|---|---|
| 1 | 319 |
| 10 | 7 |
| 100 | 6 |
| n=332 · mean=0 | |
For each peer we sync with, RBSR computes "blobs the peer has that I don't" and asks bitswap to fetch them. This histogram is the size of that wantlist per peer-sync.
≤ 1 or ≤ 10 buckets — the diff is small because we already have most of what each peer has.≤ 1000+ buckets. Each one means we asked bitswap to fetch hundreds-to-thousands of blobs from this peer. If the putBlock disposition → exists share is also high, RBSR is undercounting our local set: it tells every peer we're missing blobs we actually have, peers ship them, the blockstore drops them, and the next sync repeats. Combined with the 2-minute TimeoutPerPeer hard cap, large wantlists trigger the sync — late-cancellation waste path.| phase | p10 | p50 | p90 | p99 | count |
|---|---|---|---|---|---|
| auth_resolve | 143µs | 716µs | 367ms | 416ms | 119 |
| load_store | 3ms | 8ms | 29ms | 139ms | 119 |
| rbsr_session | 100µs | 500µs | 900µs | 990µs | 118 |
| rbsr_reconcile | 100µs | 500µs | 900µs | 990µs | 118 |
| total observations: 474 | |||||
When OTHER peers call our ReconcileBlobs RPC, where does our time go? Same Go code runs on gateways, so this is a structural proxy for what they spend per request.
structural_blobs + blob_links. Scales with corpus size — a heavy gateway will spend a lot here.| row | p10 | p50 | p90 | p99 | count |
|---|---|---|---|---|---|
| TOTAL | 3ms | 11ms | 371ms | 416ms | 119 |
| total observations: 119 | |||||
Whole-handler wall-clock for inbound ReconcileBlobs requests. Compare directly against the client-side reconcile_rpc row higher up. If client p99 ≫ server p99, the gap is in the network/stream layer between us, not on either CPU.
| limit | 16 |
| in_flight | 0 |
| waiting | 0 |
| accepted_total | 119 |
| rejected_total | 0 |
| queue_wait p50/p90/p99 | 500µs / 900µs / 990µs (n=119) |
Backpressure in front of inbound ReconcileBlobs. Default limit is max(2, 2*GOMAXPROCS); callers wait up to 3s for a slot, then receive ResourceExhausted.
| <= blobs | count |
|---|---|
| 1 | 47 |
| 4 | 4 |
| 16 | 3 |
| 64 | 6 |
| 256 | 12 |
| 1024 | 37 |
| 4096 | 9 |
| n=118 · mean=382 | |
How many blobs the RBSR set ends up holding for one inbound request. Bigger store → more compute everywhere. A mean around 1-10 means most filters are tight; spikes into 1000+ mean a recursive filter pulled in a heavy account.
| call | p10 | p50 | p90 | p99 | count |
|---|---|---|---|---|---|
| new_conn | 12ms | 42ms | 76ms | 85ms | 5 |
| reused_conn | 22ms | 96ms | 1.80s | 3.23s | 462 |
| total observations: 467 | |||||
Per-round timing of our outbound ReconcileBlobs calls, split by whether the gRPC conn map already had a live connection to that peer at the start of the round.
hmnet.Client.conns, so this round skipped the dial and went straight to the request.If new_conn p99 is dramatically higher than reused_conn p99, dial cost is the bottleneck. If they're comparable, time is being spent on the gateway side, not the wire.
| outcome | count |
|---|---|
| ok | 332 |
| protocol_mismatch | 132 |
| dial_failed | 10 |
| rpc_error | 59 |
| preempted | 11 |
| putmany_failed | 0 |
| total: 544 | |
Cumulative counter for how each sync-with-peer call ended.
Highlighted red if any non-ok row is >5% of total. protocol_mismatch volume is fine; the others should be near zero.
| layer | loopback in | loopback out | remote in | remote out | total |
|---|---|---|---|---|---|
| libp2p | 0 B | 0 B | 7.6 MiB | 5.0 MiB | 12.6 MiB |
| http server | 250.5 KiB | 61.8 MiB | 0 B | 0 B | 62.0 MiB |
| http client | 0 B | 0 B | 0 B | 0 B | 0 B |
| TOTAL | 250.5 KiB | 61.8 MiB | 7.6 MiB | 5.0 MiB | 74.6 MiB |
| protocol | scope | recv | sent |
|---|---|---|---|
/hypermedia/0.9.2 | remote | 7.5 MiB | 4.7 MiB |
/libp2p/circuit/relay/0.2.0/hop | remote | 55.8 KiB | 88.5 KiB |
/ipfs/id/1.0.0 | remote | 73.2 KiB | 52.7 KiB |
/ipfs/id/push/1.0.0 | remote | 1.7 KiB | 106.9 KiB |
/libp2p/circuit/relay/0.2.0/stop | remote | 34.3 KiB | 25.4 KiB |
/libp2p/autonat/2/dial-request | remote | 748 B | 2.8 KiB |
(unlabeled) | remote | 1.6 KiB | 1.6 KiB |
/libp2p/dcutr | remote | 1.1 KiB | 1.1 KiB |
| peer ID | scope | recv | sent | last activity |
|---|---|---|---|---|
12D3KooWKXHnBR2kwtaZTePYKTh3FQuaSQVcpMwSwobLeVkuWjPC | remote | 3.1 MiB | 404.4 KiB | just now |
12D3KooWEDdEeuY3oHCSKtn1eC7tU9qNWjF9bb8sCtHzpuCjvomQ | remote | 2.9 MiB | 299.2 KiB | just now |
12D3KooWDpmAhwAikLEJiNFeVNVsQwT6pc1MonouETsSCbTustny | remote | 144.6 KiB | 2.9 MiB | just now |
12D3KooWFUUkhfHSWhpXzpobjYHFCMEgwTpGb8PDxJCwR7LnaHP4 | remote | 961.8 KiB | 773.4 KiB | just now |
12D3KooWJ9dFfLCAwBCa9ecER5DQxP9mBMAfc2AA9Meeg2VXS8Jn | remote | 208.0 KiB | 185.1 KiB | just now |
12D3KooWRwuDfVK9BXqk7meYSZjWQn4jM8xKHUxLi41cP4AqTSPv | remote | 131.4 KiB | 192.2 KiB | just now |
12D3KooWAYFkZDCdU1LxM75ja9rybPKrVUjkcz5PCcgW8p57SoEz | remote | 89.7 KiB | 80.8 KiB | just now |
12D3KooWGvsbBfcbnkecNoRBM7eUTiuriDqUyzu87pobZXSdUUsJ | remote | 59.1 KiB | 81.3 KiB | 2s ago |
12D3KooWNmjM4sMbSkDEA6ShvjTgkrJHjMya46fhZ9PjKZ4KVZYq | remote | 33.5 KiB | 55.4 KiB | 12s ago |
12D3KooWA941vPwW1RhF1YQzEm9FvXUyTsLHqN52RbyEVGtvvcAG | remote | 46.5 KiB | 29.1 KiB | just now |
| tag | scope | recv | sent |
|---|---|---|---|
| grpc-web | loopback | 250.5 KiB | 61.7 MiB |
| debug | loopback | 0 B | 36.2 KiB |
| other | loopback | 0 B | 102 B |
| blocks received | 0 |
| data received | 0 B |
| duplicate blocks received | 0 |
| duplicate data received | 0 B (—) |
| blocks sent | 0 |
| data sent | 0 B |
| new (fresh insert into blobs) | 0 blocks · 0 B |
| update (placeholder filled) | 0 blocks · 0 B |
| exists (already had it, dropped) | 0 blocks · 0 B (— of bytes) |
blobs in blobs but NOT in structural_blobs | 18743 (3.9 GiB) |
| dag-cbor (Hypermedia structural — should be indexed) | 0 |
| dag-pb (UnixFS chunks — usually fine to be unindexed) | 0 |
| other codec | 18743 |
CIDs skipped before bitswap (would have hit putBlock as exists) | 137 |
| at startup | 4.0 GiB |
| now | 4.0 GiB |
| grew by | 16.0 KiB |
| elapsed since startup snapshot | 45s |
Where the daemon's bytes are going since startup. Three layers are tracked independently — they don't double-count each other:
/ipfs/<cid>), debug pages. The desktop app's gRPC-Web traffic shows up here as loopback since the frontend connects to 127.0.0.1.scope: loopback means the remote endpoint is 127.0.0.0/8 or ::1. remote means anything else, including LAN. So if your bandwidth feels too high but the loopback row is the dominant chunk, the bytes never left the machine.
bitswap duplicate-block waste: bitswap broadcasts WANT messages to every connected peer. When several peers race to send the same block, we accept all copies. Duplicate data received is the share of the bitswap recv stream that was wasted on blocks we already had. A high value (red >20%) means most of the bitswap inbound traffic is amplification, not new content. Multiplied across a few hundred connected peers this is usually the dominant source of "why is my bandwidth so high".
putBlock disposition: every block that reaches our blockstore (delivered by bitswap or pushed via PutMany) goes through one of three branches in blockStore.putBlock: new writes a fresh row, update fills in a previously-known placeholder, exists means we already had a complete row and the data is dropped. A large exists share (red >20%) means we paid full network cost to receive content already on disk — i.e. RBSR or bitswap thought we were missing blobs we actually have. Cross-check against SQLite size — this session below: if the DB barely grew but bitswap recv was big, the exists row is almost certainly where it went.
codec mismatch: when a peer ships a block, the bitswap-delivered CID carries a codec (raw, dag-pb, dag-cbor, …). When that block reaches putBlock and we already have the same multihash stored under a different codec, we hit the exists branch and drop the data. RBSR's set diff identifies items by full CID — codec + multihash — so two valid encodings of the same content (e.g. small UnixFS files stored as raw by some peers and as dag-pb by others) look like different items and get repeatedly fetched and dropped. Each row is a (stored→incoming) codec pair we observed, with the count of redundant deliveries. Empty table means peers and us agree on codecs; non-empty means we're paying real bandwidth for content we already have under a different CID.
syncing pre-flight Has filter: after RBSR computes a wantlist of CIDs the peer has and we don't, we run a multihash-keyed blockstore.Has on each before handing it to bitswap. CIDs we already have (codec mismatch or scope/orphan reachability — see the codec-mismatch table above) get filtered out at zero network cost, sparing us the WANT_HAVE → HAVE → WANT_BLOCK → BLOCK round-trip and the block delivery itself. The counter shows lifetime saved fetches; expect it to grow at the rate putBlock disposition: exists would have grown without the filter. A green non-zero value is direct inbound bandwidth saved; zero on a freshly-started daemon is normal.
blob index drift: count of rows in blobs with size >= 0 that have NO matching row in structural_blobs. RBSR builds its local-set view from structural_blobs via collectBlobs, so these blobs are present on disk but invisible to the diff. Each one will be re-fetched from peers every sync cycle and dropped at putBlock as exists. Red when the dag-cbor count is non-zero — those should be indexed and aren't.
persist pipeline — failures: post-streaming-refactor, fetched blocks are pipelined into PutMany batches and persisted on a detached ctx. Two failure modes can show up:
PutMany tx rolled back, most often because indexBlob hit a cross-blob reference whose referent isn't in the DB yet (e.g. a Change ahead of its genesis_blob, a Capability before its parent). Those blocks come back from peers next sync and the order resolves. A small steady value during initial big syncs is expected; a sustained high value points at a real ordering / dependency bug worth chasing.SQLite size — this session: page_count × page_size sampled at daemon start vs now. Compared against bitswap unique-recv (data received minus duplicates). If vs bitswap unique recv is much less than 1, then unique blob bytes were received from peers but didn't reach disk — either still buffered, dropped by indexer validation, or never persisted. If it's roughly 1×, the on-the-wire bytes really did become disk bytes. The ratio assumes blob content is incompressible-ish; if your storage path applies compression this ratio drops accordingly without indicating a leak.
All counters reset on daemon restart; numbers are cumulative since then.
| peer ID | state |
|---|---|
12D3KooWA3STw1Jwczh6q9XWFDrPkeSLJ2jjHWLWBt5vUb9CixR7 | Connected |
12D3KooWA941vPwW1RhF1YQzEm9FvXUyTsLHqN52RbyEVGtvvcAG | Connected |
12D3KooWAYFkZDCdU1LxM75ja9rybPKrVUjkcz5PCcgW8p57SoEz | Connected |
12D3KooWDpmAhwAikLEJiNFeVNVsQwT6pc1MonouETsSCbTustny | Connected |
12D3KooWEDdEeuY3oHCSKtn1eC7tU9qNWjF9bb8sCtHzpuCjvomQ | Connected |
12D3KooWFUUkhfHSWhpXzpobjYHFCMEgwTpGb8PDxJCwR7LnaHP4 | Connected |
12D3KooWGvsbBfcbnkecNoRBM7eUTiuriDqUyzu87pobZXSdUUsJ | Connected |
12D3KooWJ9dFfLCAwBCa9ecER5DQxP9mBMAfc2AA9Meeg2VXS8Jn | Connected |
12D3KooWKXHnBR2kwtaZTePYKTh3FQuaSQVcpMwSwobLeVkuWjPC | Connected |
12D3KooWMjs8x6ST53ZuXAegedQ4dJ2HYYQmFpw1puGpBZmLRCGB | Connected |
12D3KooWNmjM4sMbSkDEA6ShvjTgkrJHjMya46fhZ9PjKZ4KVZYq | Connected |
12D3KooWRwuDfVK9BXqk7meYSZjWQn4jM8xKHUxLi41cP4AqTSPv | Connected |
QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN | Connected |
QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa | Connected |
QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ | Connected |
QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb | Connected |
QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt | Connected |
12D3KooW9wyhDTWkCRwAWtG5TSGX5HsiG951RQeu95L57BAVU7yU | NotConnected |
12D3KooW9ydMdN9ZLtTezCbYnV8KjbwKksKqXALHJSzUSAeJAP6q | NotConnected |
12D3KooWA3kRW5jqZT7xRNkoAtdkbmqB44WhaxA56bLMxD7xZtBT | NotConnected |
12D3KooWA5FjyXqEBKbVrQJ4Ji36KQyYtYHJnQhzXAPhTufea2nS | NotConnected |
12D3KooWA7Mno2F6qenfSSHU4KmShEbR6Ug3o8QbCDR6k1A8Mi1B | NotConnected |
12D3KooWA7ZsxRXPXmpwWFDHee54AqGzsB5Vwc1umh31zoea5JTF | NotConnected |
12D3KooWA7vh7B9gx14zJKQ2MEV6Vq7VPF1Lrsi9oXVxPosd1P4d | NotConnected |
12D3KooWA7xgeGdPcu6irSyfveTQc99EFsL5TG4tB5Ex9cFqpWYX | NotConnected |
12D3KooWA8gyoqr7Npn2N1AvYTzFSARuVd6YZFKFbY3MeMSnUkPe | NotConnected |
12D3KooWA9JZcQJ3cVUtKyWy19myRfNZdYbrpX8fmoe8y3yUbGE4 | NotConnected |
12D3KooWA9rYRVbadonwyEy1msv1ABcc26tWVN35tPoSZhCaCtaW | NotConnected |
12D3KooWAEAa7bTRxerJGaMCM2C3sYzYUuqwpFgoLjx6m797HMEf | NotConnected |
12D3KooWAHmrt9ui89aqBfNYDLWRn67ice3mTKe2xKTSBGiKn5c7 | NotConnected |
| … 323 more | |