A stake pool's relay set is the one piece of its infrastructure anyone can verify without trusting the operator — it is registered on-chain, in the same certificate as the pledge and the margin. This page reports what every current pool registered, which pools share infrastructure, and which endpoints answered a real Cardano handshake.
Loading the published cut…
This dataset is deliberately not a scoreboard. It has two layers and they are kept apart on purpose, because only one of them is durable.
What each pool registered on-chain, when, and which endpoint strings more than one pool advertises. Reproducible by anyone with db-sync.
That an endpoint did or did not complete a handshake with our prober, at that moment, from one network location. It expires.
That any relay is “offline”. Who operates any pool. That shared infrastructure means shared ownership. That any operator is negligent.
The durable layer. A pool's live registration is its latest pool_update;
a retirement counts only if it was announced after that update and its epoch has arrived.
| Registration | Pools | ADA delegated |
|---|
Every number above aggregates relay_pool_health.csv, extracted by build_relay_registration.sql. Reproducible from db-sync alone: run it and you should get these exact rows.
A two-pass node-to-node handshake sweep of every registered endpoint — a real Cardano handshake plus a tip request, not a TCP connect. Reachable hosts are counted as distinct resolved hosts, never as registration entries: two DNS names pointing at one machine is one relay.
| Observed | Pools | ADA | Delegators |
|---|
Unreachability tracks stake almost monotonically. A uniformly broken probe would not produce that gradient — pools abandoned without ever filing a retirement certificate would.
| Active stake | Pools | Nothing answered | Share |
|---|
Why each endpoint failed. no_ipv6_at_probe means our prober has no IPv6 route and did not test the endpoint at all — those pools are reported as untested, not as unreachable.
| Failure | Endpoints |
|---|
Every number above aggregates relay_endpoint_status.csv, relay_pool_health.csv, produced by relay_probe.py, build_relay_reachability.sql. This half is a live measurement, so your own run will differ from this one.
Read on its own, the count of pools where nothing answered is badly misleading — most of them are abandoned registrations whose operator never filed a retirement certificate. They inflate every per-pool count of Cardano's “3,000 pools” and they hold almost no stake. The honest cut is pools that actually produced a block in the last 30 epochs.
| Observed | Minting pools | ADA | Idle pools | ADA |
|---|
Aggregates relay_pool_health.csv. Mixed: the block counts come from db-sync via build_relay_reachability.sql and reproduce exactly; the reachability columns come from the sweep and will not.
Pool registrations are append-only. A pool can change what it advertises; it can never un-publish what it advertised before. That matters, because removing a relay from the certificate is an ordinary transaction — no new deposit, just the fee — and it makes an unreachable relay stop being unreachable by making it stop existing. This is the one view where publishing less makes a pool more visible, not less.
| Direction | Certificates | Pools |
|---|
Every pool that registers no relay and is producing blocks — whether it removed relays it once had, or never advertised any:
| Ticker | ADA | Delegators | Blocks / 30ep | Previously advertised |
|---|
Stake is a current snapshot; blocks are a 30-epoch total. A pool that recently lost delegation will show many blocks against little stake — BD3 held 56.7M ADA until epoch 646 and about 190k after it, and earned its blocks on the former. That is a change in delegation, not an anomaly.
The obvious dismissal is that pools without relays are abandoned ones nobody retired. Seventeen of them are exactly that — they hold 47,625 ADA between them and have produced nothing. But by rate, the behaviour peaks again among established mid-size pools with thousands of delegators.
| Pool size | No relay | All pools | Rate | Share |
|---|
Registering no relay is permitted, and operators who do it
usually cite DDoS surface. What it means factually is that the network cannot discover them from
the chain, and their inbound load sits on the pools that do publish. Every one of these events
carries its transaction hash in relay_registration_changes, so none of it has to be
taken on trust.
Every number above aggregates relay_registration_changes.csv, relay_pool_health.csv, extracted by build_relay_registration.sql. Reproducible from db-sync alone: run it and you should get these exact rows. Certificate history is append-only, so it is the same for everyone, forever.
Reachability alone can be gamed, and until this section existed this dataset was rewarding the gaming. A pool that registers the founding entities' bootstrap backbones scores the best available grade here — many reachable hosts, all at the tip — because those endpoints genuinely do answer. They are IOG's, the Cardano Foundation's and Emurgo's. It also slips past every sharing check on this page: no other pool registers the same strings, so endpoint, resolved-host and domain matching all see nothing. Spotted by @HephyPool.
| Ticker | ADA | Delegators | Pledge | Blocks | Foreign / total | Advertises |
|---|
backbone.* names are the bootstrapPeers shipped in the stock mainnet
topology.json — the network's shared entry points, published so any node can
find its first peers. They are nobody's relays, and the founding entities' own pools do not
register them either: IOG1 advertises iog1-relays.cardano.iog.io, the CF pools
advertise cfNrN.mainnet.pool.cardanofoundation.org. So no allowlist of identities
is needed to read this table.That a pool registered these strings is fact, straight from the chain. What it means is the reader's call: a misconfiguration and a deliberate free-ride look identical on-chain and this table does not try to separate them. What it does mean is that the pool publishes no way to reach its node, and its inbound load sits on infrastructure it does not run.
Every number above aggregates relay_foreign_infrastructure.csv, extracted by build_relay_foreign_infra.sql. Reproducible from db-sync alone: run it and you should get these exact rows.
A pool with three relays is not redundant if all three sit in one datacenter. Pool counts cannot see that; the network announcing each reachable relay IP can.
| Network | Country | Pools | ADA | Wholly inside | Their ADA |
|---|
Aggregates relay_asn_concentration.csv, produced by relay_asn_lookup.py, build_relay_concentration.sql. This half is a live measurement, so your own run will differ from this one. ASN ownership comes from Team Cymru's public IP-to-ASN DNS service.
Four measured traps. Each one produced a confident, wrong answer during the build before it was caught — which is the whole reason the method is published alongside the numbers.
backbone.cardano.iog.io answers in 5.2s; Trust Wallet's Kiln-hosted relays take
14–30s — both reporting a protocol RTT near 100ms. A first sweep at a 10s timeout marked
TW001, with 113.6M ADA delegated, as having no reachable relay. It answers fine. Every
non-DNS failure now gets a slower, lower-concurrency second pass, and only a failure in both
passes is recorded._cardano._tcp.<domain>, and each target
carries its own port from DNS. cardano-cli ping does not resolve SRV at all: hand
it one and it does a plain A lookup on port 3001 and reports a bogus failure.The prober is relay_probe.py; the full method and its limits are 27_RELAY_HEALTH_METHOD.md and the graded write-up is F21_relay_registration_and_reachability.md.
All of it is in the repo — no API key, no rate limit, no server to ask. Clone it or pull a CSV straight from raw.githubusercontent.com.
| Table | What it holds |
|---|---|
| relay_pool_health | One row per current pool: registration shape, reachable hosts, at-tip hosts, shared-endpoint flag, last_checked. |
| relay_shared_endpoints | Endpoint strings advertised by more than one current pool. |
| relay_shared_hosts | Pools sharing a resolved IP — catches per-pool hostnames. |
| relay_shared_domains | Pools sharing a parent domain (heuristic; groups hosting customers too). |
| relay_asn_concentration | Per network: pools, stake, and how many have their entire reachable relay set inside it. |
| relay_foreign_infrastructure | Pools advertising founding-entity bootstrap backbones as their own relays. |
| relay_registration_changes | Every certificate that changed a pool’s relay count — date, tx hash, before/after, direction. |
| relay_endpoint_status | The raw per-endpoint sweep, with failure cause and detail. |
Method and limits — which bind any use of these numbers — are in docs/27. The graded write-up is F21, the build is sql/56_relay_health. For an operator-clustering signal that does not depend on registration strings at all, see F10 — synchronized KES rotation, read from block headers.