DePIN capacity vs demand — brief for 2026-08-28
Generated 2026-08-28T08:00:01Z. Every number is measured, carries its source and as-of time, and can be re-derived from the live API. Windows are stated; nothing is interpolated or forecast.
MarkdownJSONLive API (free, no key)
What is scarce here. Both halves of a utilisation ratio — capacity AND consumption — on 6 networks: AKT, FIL, FLUX, IO, SC, TFT. Node counts are public everywhere; the denominator is not. This is the entire reason the ledger below can exist, and it is why coverage, not commentary, is what we sell.
The sharpest thing the data says this week. AKT gpus: utilisation 31.64% → 61.65%, with demand growing 97.22pp faster than capacity over the window. Demand is outrunning capacity: the constraint is onboarding, not adoption, and utilisation headroom is the thing to underwrite.
12 stale dashboard(s) caught · 148 of 219 token supplies confirmed by our own chain reads.
The allocator's ledger — capacity vs demand
Is this network adding capacity faster than demand absorbs it?
| Network | Resource | Utilisation | Supply Δ | Demand Δ | Divergence | Read |
|---|---|---|---|---|---|---|
| AKT | storage_bytes | 7.98% → 7.32% | 15.42% | 5.91% | 9.52pp | overcapacity building |
| IO | devices | 57.28% → 53.37% | 2.28% | -4.69% | 6.98pp | overcapacity building |
| FLUX | compute_cores | 16.93% → 16.78% | 0.84% | -0.05% | 0.89pp | balanced |
| FLUX | memory_bytes | 9.65% → 9.61% | 0.58% | 0.22% | 0.37pp | balanced |
| FLUX | storage_bytes | 5.18% → 5.17% | 0.75% | 0.68% | 0.07pp | balanced |
| FIL | storage_bytes | 87.89% → 87.85% | 0.0% | -0.04% | 0.04pp | balanced |
| TFT | memory_bytes | 13.87% → 14.43% | -3.06% | 0.81% | -3.87pp | balanced |
| SC | storage_bytes | 25.85% → 27.01% | -0.53% | 3.94% | -4.47pp | balanced |
| TFT | compute_cores | 15.02% → 16.1% | -2.04% | 4.97% | -7.01pp | demand outpacing supply |
| AKT | memory_bytes | 14.92% → 25.65% | -2.89% | 67.02% | -69.92pp | demand outpacing supply |
| AKT | compute_cores | 20.55% → 36.45% | -7.48% | 64.12% | -71.6pp | demand outpacing supply |
| AKT | gpus | 31.64% → 61.65% | 2.54% | 99.76% | -97.22pp | demand outpacing supply |
| TFT | storage_bytes | 0.0% → 0.0% | 2.34% | % | 0pp | balanced |
Positive divergence = capacity onboarding faster than demand absorbs it — utilisation falls even while the headline node count rises. One window, not a trend. Descriptive, not a forecast.
Pairs we can compute and refuse to publish
A refusal you cannot audit is just a different kind of marketing, so each reason is published in full.
IO gpus
io.net's GPU_TOTAL is NOT registered GPU supply — it equals DEVICES_ACTIVE exactly on every archived day (1,213/1,213 ... 1,199/1,199), and GPU_HIRED + GPU_IDLE == GPU_TOTAL exactly. So hired/total is a FILL RATE on the already-active pool, near-tautological, and it excludes every passive device. It reads 96.7% while true device utilisation (active/registered) is 46.2% and FALLING — registered devices grew 2,057 -> 2,594 (+26%) in 7 days while active stayed flat near 1,200. Publishing 96.7% beside Akash's 30.5% (utilisation of REGISTERED capacity) would invert the actual story: io.net is the network accumulating idle supply fastest, not the one running hottest.
NOS devices
NOSANA HAS NO PUBLISHABLE DENOMINATOR (probed 2026-08-24, recorded so the next agent does not re-probe it). The numerator is free and clean — dashboard.k8s.prd.nos.ci/api/jobs?state=RUNNING reports totalJobs=947 running jobs and each Nosana job occupies exactly one node. The denominator is not: /api/nodes and /api/nodes/stats require an authorization header (401 with one, 422 without), and no unauthenticated sibling exposes a node count. Two tempting substitutes were REFUSED. (1) running + queued NODES from /api/markets: that per-market queue holds only IDLE nodes and is 0 across all 47 markets while 43 jobs sit QUEUED, so the denominator would equal the numerator by construction and publish a tautological 100%. (2) per-market access-SFT supply on Solana (231 for the nvidia-3070 market): a node joining three markets holds three SFTs and nothing burns them when it leaves, so the sum counts memberships and departed nodes, not live nodes. The numerator is collected anyway (collectors_clean/nosana_utilisation.py writes NOS JOBS_RUNNING/JOBS_QUEUED/MARKET_IDLE_NODES) so the pair can complete the day Nosana publishes a node count; no ratio until then.
SC devices
SIACOIN'S DENOMINATOR IS CUMULATIVE, NOT LIVE (measured 2026-08-24). Both halves flow — SC_ACTIVE_HOSTS ~530, SC_TOTAL_HOSTS ~87,048 — so the pair LOOKS complete and would auto-publish a 0.6% utilisation figure. It is not a utilisation figure: TOTAL_HOSTS counts every host ever announced to the Sia network and is monotonically non-decreasing across all 19 archived days (87,032.7 → 87,048.0, never once falling), while ACTIVE_HOSTS moves both ways in the 514-556 band. A denominator that can only grow makes the ratio a function of the network's AGE, so it would fall forever regardless of how the network performs — the Storj denominator trap in a new costume. The numerator is honest and stays queryable; no ratio until Sia publishes a currently-announced host count.
STORJ storage_bytes
STORJ PUBLISHES NO CAPACITY DENOMINATOR (measured 2026-08-24). Everything public is the numerator: stats.storjshare.io/data.json gives bytes stored by customers (53.4 PB) and the node-side footprint after erasure coding (92.2 PB, 1.73x), and the per-satellite node counts are memberships, not capacity — a node serving three satellites is counted three times, which is the same double-count that already inflated STORJ node totals. Nothing upstream states how many bytes the network could hold, so any utilisation ratio would need a denominator we invented. The numerator stays collected and is now correctly labelled storage_bytes_in_use rather than storage_bytes_total, which is what it had been resolving to.
Frozen feeds — the stale-dashboard detector
A first-party metric with exactly ONE distinct value across >=20 polls spanning >=5 days, while other metrics on the same network keep moving. The feed answers, but the number is stale at the source — invisible to uptime monitoring.
- TFT
HRU_USED— unchanged at 0 for 10d across 215 polls, while 16 other metric(s) on TFT kept moving - GRASS
daily_gb_collected— unchanged at 96950 for 10d across 239 polls, while 1 other metric(s) on GRASS kept movingRe-queried upstream live while writing this brief:https://api.getgrass.io/networkStats?input=%7B%22cluster%22%3A%22mainnet%22%7Dreturned96950— upstream itself is serving the same static value — the freeze is at the source, not in our collector. - TFT
HRU_UTILISATION_PCT— unchanged at 0 for 10d across 215 polls, while 16 other metric(s) on TFT kept moving - GRASS
daily_gb_multimodal— unchanged at 86474 for 7d across 157 polls, while 1 other metric(s) on GRASS kept moving - GRASS
daily_gb_text— unchanged at 1676 for 7d across 157 polls, while 1 other metric(s) on GRASS kept moving - GLM
gpus_online— unchanged at 0 for 6d across 136 polls, while 4 other metric(s) on GLM kept moving - SN24
SUBNET_ACTIVE_NEURONS— unchanged at 7 for 5d across 20 polls, while 4 other metric(s) on SN24 kept moving - IO
devices_a100_80g_pcie_spot_active— unchanged at 0 for 5d across 68 polls, while 47 other metric(s) on IO kept moving - SN94
SUBNET_ACTIVE_NEURONS— unchanged at 12 for 5d across 20 polls, while 4 other metric(s) on SN94 kept moving - SN77
SUBNET_ACTIVE_NEURONS— unchanged at 11 for 5d across 20 polls, while 6 other metric(s) on SN77 kept moving - IO
devices_geforce_rtx_4090_active— unchanged at 617 for 5d across 120 polls, while 47 other metric(s) on IO kept moving - IO
devices_a100_80g_sxm4_active— unchanged at 0 for 5d across 120 polls, while 47 other metric(s) on IO kept moving
Supply verifiability — what we confirm on-chain ourselves
148 of 219 networks reconcile to within 1% — those figures are independently confirmed, not taken on trust. The rest are listed with the exact contract we read so you can check in one click.
| Network | Chain read | Aggregator says | Verifiable | Contract |
|---|---|---|---|---|
| RIZ | 100,000 | 4,989,887,900 | 0.0% | 0x058d411a… |
| BDX | 4,432,305 | 9,939,285,508 | 0.0% | 0x9d10a1ec… |
| GENE | 261,413 | 100,000,000 | 0.3% | 0x9df46546… |
| POKT | 15,694,093 | 2,351,355,446 | 0.7% | 0x764a726d… |
| DEUS | 8,697,929 | 1,000,000,000 | 0.9% | 7JoGUTeaXk… |
| OORT | 20,000,000 | 1,998,900,000 | 1.0% | 0x5651fa7a… |
| EWT | 917,463 | 81,071,825 | 1.1% | 0x178c820f… |
| OCTA | 1,173,602 | 44,907,921 | 2.6% | 0xfa704148… |
| NMT | 3,856,323 | 143,518,642 | 2.7% | 0x03aa6298… |
| BTT | 36,542,206,310,204 | 990,000,000,000,000 | 3.7% | 0xc6699281… |
| SDM | 37,781,538 | 1,000,000,000 | 3.8% | 0x9cfe02eb… |
| NTMPI | 19,055,147 | 399,963,020 | 4.8% | 0x53be7be0… |
| LOOPIN | 3,235,636 | 56,551,875 | 5.7% | 0x975da7b2… |
| SLC | 6,075,929,002 | 98,797,933,055 | 6.2% | 0x6bd83abc… |
| GNUS | 1,000,000 | 15,193,848 | 6.6% | 0x61457703… |
Verify any of this yourself
This brief is machine-readable and free — no key, no signup:
curl https://kairossignal.com/v1/brief
Every row ships source, as_of and a verify URL pointing at the origin rather than at us. If you can refute a number here, we would rather publish the correction than the number.