Kairos Signal · All briefs · Pricing

DePIN capacity vs demand — brief for 2026-10-21

Generated 2026-10-21T08: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 5 networks: AKT, FIL, FLUX, SC, TFT; plus an active-device share (active devices divided by total devices — connected, hired or idle, not consumption) on IO. 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 in this edition. FLUX memory_bytes: utilisation 9.65% → 6.29%, with capacity growing 38.25pp faster than demand over 2026-08-24 → 2026-10-20 (57d). Capacity grew faster than recorded use over this window. This describes relative growth; it does not establish falling provider revenue or its cause.

12 candidates with unchanged stored observations (cause unverified) · 149 of 221 token supplies confirmed by our own chain reads.

The Allocator's Ledger — capacity vs demand, and active-device share

For utilisation rows: is this network adding capacity faster than recorded use absorbs it? For active-device share rows (resource: devices): are total devices growing faster than active devices? That share measures neither use nor demand.

NetworkResourceWindowRatio, start → endDenominator ΔNumerator ΔDivergenceRead
FLUXmemory_bytes2026-08-24 → 2026-10-20 (57d)utilisation9.65% → 6.29%capacity9.93%recorded use-28.32%38.25ppcapacity growth exceeds use growth
FLUXcompute_cores2026-08-24 → 2026-10-20 (57d)utilisation16.93% → 12.06%capacity9.03%recorded use-22.32%31.35ppcapacity growth exceeds use growth
FLUXstorage_bytes2026-08-24 → 2026-10-20 (57d)utilisation5.18% → 3.7%capacity6.73%recorded use-23.76%30.49ppcapacity growth exceeds use growth
FILstorage_bytes2026-08-24 → 2026-10-20 (57d)utilisation87.89% → 90.0%capacity-8.25%recorded use-6.05%-2.21ppgrowth rates within 5pp
TFTmemory_bytes2026-08-24 → 2026-10-20 (57d)utilisation13.87% → 15.14%capacity-9.8%recorded use-1.55%-8.24ppuse growth exceeds capacity growth
IOdevices2026-08-06 → 2026-10-20 (75d)active-device share57.28% → 67.44%total devices-11.9%active devices3.73%-15.63ppactive-device growth exceeds total-device growth
SCstorage_bytes2026-08-20 → 2026-10-20 (61d)utilisation25.85% → 30.31%capacity-6.62%recorded use9.52%-16.14ppuse growth exceeds capacity growth
AKTstorage_bytes2026-08-17 → 2026-10-20 (64d)utilisation7.98% → 10.19%capacity-13.5%recorded use10.49%-23.99ppuse growth exceeds capacity growth
TFTcompute_cores2026-08-24 → 2026-10-20 (57d)utilisation15.02% → 19.38%capacity-8.75%recorded use17.73%-26.49ppuse growth exceeds capacity growth
AKTcompute_cores2026-08-09 → 2026-10-21 (73d)utilisation20.55% → 27.76%capacity-6.05%recorded use26.93%-32.98ppuse growth exceeds capacity growth
TFTstorage_bytes2026-08-24 → 2026-10-20 (57d)utilisation0.0% → 0.0%capacity12.79%recorded usen/an/anot comparable

Divergence is denominator growth minus numerator growth. For utilisation rows the denominator is capacity and the numerator is recorded use; this does not establish paid demand, revenue, or a capacity bottleneck. Active-device share rows (resource: devices) divide active devices by total devices; 'active' means connected, hired or idle, not in use, so that share is not utilisation and not demand. Each row states its own window. Undefined growth is n/a. One window per row, 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 — on every archived day when this refusal was recorded it equalled DEVICES_ACTIVE exactly, and GPU_HIRED + GPU_IDLE equals GPU_TOTAL exactly. So hired/total is a FILL RATE on the already-active pool, near-tautological, and it excludes every passive (registered but not connected) device. io.net's 'active' means connected through its worker, hired or idle, not in use. Publishing that fill rate beside other networks' utilisation of REGISTERED capacity would compare different quantities. The share of registered devices that are active is reported separately as the IO devices pair — an active-device share (active devices divided by total devices), computed from data for its own window rather than typed here.

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.

Unchanged observations — cause unverified

Exactly one distinct stored value across >=20 observations spanning >=5 days, while other metrics on the same network change. Counts are stored observations, not independently verified poll attempts. Metric-name hints rank candidates; they do not establish expected cadence. Constant values and single upstream rechecks do not prove a stopped feed. No statistical failure probability is claimed.

Supply verifiability — what we confirm on-chain ourselves

149 of 221 networks reconcile to within 1% — those figures are independently confirmed, not taken on trust. Of the other 72, 54 are more than 10% off; the 15 with the lowest ratios are listed with the exact contract we read so you can check in one click.

A low ratio is a statement about ONE deployment on ONE chain, not a claim that the aggregator is wrong. Multi-chain tokens (native chain + bridged ERC-20) legitimately show low ratios: e.g. POKT and BTT are native elsewhere and only their wrapped portion is readable on the chain we poll. Verified 2026-08-24 that our reads are faithful to the contract: RIZ reads 100,000 on 0x058d411a..., byte-identical to the explorer's own figure for that contract.
NetworkChain readAggregator saysVerifiableContract
BDX1,153,3679,939,718,2450.0%0x9d10a1ec…
GENE261,413100,000,0000.3%0x9df46546…
POKT17,402,6242,375,352,2310.7%0x764a726d…
OORT20,000,0001,998,900,0001.0%0x5651fa7a…
DEUS10,102,3631,000,000,0001.0%7JoGUTeaXk…
EWT917,36081,071,8251.1%0x178c820f…
OCTA1,173,60244,907,9212.6%0xfa704148…
NMT3,831,915143,446,4152.7%0x03aa6298…
BTT36,542,206,310,204990,000,000,000,0003.7%0xc6699281…
SDM40,043,1821,000,000,0004.0%0x9cfe02eb…
NTMPI19,055,147399,963,0204.8%0x53be7be0…
LOOPIN3,296,56557,655,6995.7%0x975da7b2…
GNUS970,01915,193,8486.4%0x61457703…
SLC7,100,195,69098,797,933,0557.2%0x6bd83abc…
NODL546,469,4277,487,432,9347.3%0x6dd0e17e…

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.