NEAR investment thesis · track thesis · data to 2026-11-12
NEAR is 99.3% empty.
That empty space is the thesis. NEAR can take about 70× today's paid demand before its fees even start to rise. For gas to burn as much NEAR as is minted at the approved 1.6% issuance, it needs 61×. The room exists. The question is whether demand arrives, and this page tracks that with one number.
Research, not financial advice. Every number is rebuilt from public data with python rebuild.py; the query sits under each chart.
Repository · Method · The six signals
Right now
Your browser asks a public NEAR node for the newest blocks and adds up every shard. No server of ours is involved.
The evidence
Each chart: what it shows in one sentence, the query behind it, and the processing step. Hover a line chart to read values.
The whole thesis on one scale
For gas to burn as much NEAR as is minted at the approved 1.6% issuance, NEAR needs 644M Tgas of paid gas a day: 61 times today, 10 times its busiest month ever, and still below the half-full line where fees start to rise.
The query
analyze.py: capacity = mean daily gas_limit over the last 7 days; paid gas = mean daily gas_used over 30 days; break-even = (supply x issuance / 365.25) / NEAR burned per Tgas since the rebate ended (total supply fall / gas used, 5 to 12 Nov 2026).
-- sql/01_chunks_daily.sql
-- Headroom 01: NEAR blockspace per day and shard.
-- gas_limit is what the chain could have processed, gas_used is what it did process.
-- One row per (day, shard). A chunk is one shard's slice of one block.
-- Cost control: filters on block_date (the partition column) and reads 4 small columns.
SELECT
block_date,
shard_id,
COUNT(*) AS chunks,
SUM(gas_used) AS gas_used,
SUM(gas_limit) AS gas_limit,
COUNTIF(gas_used >= 0.5 * gas_limit) AS chunks_over_half,
COUNTIF(gas_used >= 0.8 * gas_limit) AS chunks_over_80pct,
MAX(SAFE_DIVIDE(gas_used, gas_limit)) AS max_fill
FROM `bigquery-public-data.crypto_near_mainnet_us.chunks`
WHERE block_date BETWEEN @from_date AND @to_date
GROUP BY block_date, shard_id
ORDER BY block_date, shard_id
-- sql/02_blocks_daily.sql
-- Headroom 02: gas price and total supply per day.
-- Every block header carries total_supply. Inside an epoch it only falls (gas that is burned);
-- at the first block of an epoch it jumps (new NEAR minted for validators). So the block-to-block
-- change splits cleanly into minted (rises) and burned (falls).
-- Cost control: filters on block_date and reads 5 columns.
WITH b AS (
SELECT
block_date,
block_height,
block_timestamp,
gas_price,
total_supply,
total_supply - LAG(total_supply) OVER (ORDER BY block_height) AS delta
FROM `bigquery-public-data.crypto_near_mainnet_us.blocks`
WHERE block_date BETWEEN DATE_SUB(@from_date, INTERVAL 1 DAY) AND @to_date
)
SELECT
block_date,
COUNT(*) AS blocks,
MIN(block_height) AS first_height,
MAX(block_height) AS last_height,
SAFE_DIVIDE(MAX(block_timestamp) - MIN(block_timestamp), 1e9 * (COUNT(*) - 1)) AS seconds_per_block,
MIN(gas_price) AS min_gas_price,
MAX(gas_price) AS max_gas_price,
COUNTIF(gas_price > 100000000) AS blocks_above_floor,
SUM(IF(delta > 0, delta, 0)) AS minted_yocto,
SUM(IF(delta < 0, -delta, 0)) AS burned_yocto,
COUNTIF(delta > 0) AS mint_blocks,
ARRAY_AGG(total_supply ORDER BY block_height DESC LIMIT 1)[OFFSET(0)] AS end_supply_yocto
FROM b
WHERE block_date BETWEEN @from_date AND @to_date
GROUP BY block_date
ORDER BY block_dateCapacity grew 17 times. Paid gas did not follow
NEAR can process 1.49B Tgas a day across 10 shards with 0.58-second blocks; over the last 30 days it used 10.5M, 0.72% of it.
The query
analyze.py: per day, sum gas_used and gas_limit over every chunk of every shard; weekly means.
-- sql/01_chunks_daily.sql
-- Headroom 01: NEAR blockspace per day and shard.
-- gas_limit is what the chain could have processed, gas_used is what it did process.
-- One row per (day, shard). A chunk is one shard's slice of one block.
-- Cost control: filters on block_date (the partition column) and reads 4 small columns.
SELECT
block_date,
shard_id,
COUNT(*) AS chunks,
SUM(gas_used) AS gas_used,
SUM(gas_limit) AS gas_limit,
COUNTIF(gas_used >= 0.5 * gas_limit) AS chunks_over_half,
COUNTIF(gas_used >= 0.8 * gas_limit) AS chunks_over_80pct,
MAX(SAFE_DIVIDE(gas_used, gas_limit)) AS max_fill
FROM `bigquery-public-data.crypto_near_mainnet_us.chunks`
WHERE block_date BETWEEN @from_date AND @to_date
GROUP BY block_date, shard_id
ORDER BY block_date, shard_idEven the busiest shard has room
The network is 0.72% full. Over the last 30 days the busiest shard of each day was 2.4% full on average and 25% at most. The only time a shard filled up was 01 December 2023 (98%).
The query
analyze.py: utilization = sum(gas_used) / sum(gas_limit); busiest shard = max over shards of that shard's daily ratio.
-- sql/01_chunks_daily.sql
-- Headroom 01: NEAR blockspace per day and shard.
-- gas_limit is what the chain could have processed, gas_used is what it did process.
-- One row per (day, shard). A chunk is one shard's slice of one block.
-- Cost control: filters on block_date (the partition column) and reads 4 small columns.
SELECT
block_date,
shard_id,
COUNT(*) AS chunks,
SUM(gas_used) AS gas_used,
SUM(gas_limit) AS gas_limit,
COUNTIF(gas_used >= 0.5 * gas_limit) AS chunks_over_half,
COUNTIF(gas_used >= 0.8 * gas_limit) AS chunks_over_80pct,
MAX(SAFE_DIVIDE(gas_used, gas_limit)) AS max_fill
FROM `bigquery-public-data.crypto_near_mainnet_us.chunks`
WHERE block_date BETWEEN @from_date AND @to_date
GROUP BY block_date, shard_id
ORDER BY block_date, shard_idThe price of gas has not moved since May 2024
99.89% of all 214M blocks were priced at the floor of 0.0001 NEAR per Tgas. Of the 236,622 that were not, 216,722 came in the inscriptions wave of late 2023, and 54 since May 2024.
The query
analyze.py: monthly sum of blocks_above_floor. Before 22 Aug 2020 the floor was 1e9 and no block went above it.
-- sql/02_blocks_daily.sql
-- Headroom 02: gas price and total supply per day.
-- Every block header carries total_supply. Inside an epoch it only falls (gas that is burned);
-- at the first block of an epoch it jumps (new NEAR minted for validators). So the block-to-block
-- change splits cleanly into minted (rises) and burned (falls).
-- Cost control: filters on block_date and reads 5 columns.
WITH b AS (
SELECT
block_date,
block_height,
block_timestamp,
gas_price,
total_supply,
total_supply - LAG(total_supply) OVER (ORDER BY block_height) AS delta
FROM `bigquery-public-data.crypto_near_mainnet_us.blocks`
WHERE block_date BETWEEN DATE_SUB(@from_date, INTERVAL 1 DAY) AND @to_date
)
SELECT
block_date,
COUNT(*) AS blocks,
MIN(block_height) AS first_height,
MAX(block_height) AS last_height,
SAFE_DIVIDE(MAX(block_timestamp) - MIN(block_timestamp), 1e9 * (COUNT(*) - 1)) AS seconds_per_block,
MIN(gas_price) AS min_gas_price,
MAX(gas_price) AS max_gas_price,
COUNTIF(gas_price > 100000000) AS blocks_above_floor,
SUM(IF(delta > 0, delta, 0)) AS minted_yocto,
SUM(IF(delta < 0, -delta, 0)) AS burned_yocto,
COUNTIF(delta > 0) AS mint_blocks,
ARRAY_AGG(total_supply ORDER BY block_height DESC LIMIT 1)[OFFSET(0)] AS end_supply_yocto
FROM b
WHERE block_date BETWEEN @from_date AND @to_date
GROUP BY block_date
ORDER BY block_dateNEAR mints a hundred times what it burns
Over the last 30 days NEAR minted 89,536 NEAR a day and burned 832: burn covered 0.93% of new supply, even after the 2025 issuance cut.
The query
analyze.py: a block's total_supply minus the previous block's; rises are minting (first block of each epoch), falls are burning.
-- sql/02_blocks_daily.sql
-- Headroom 02: gas price and total supply per day.
-- Every block header carries total_supply. Inside an epoch it only falls (gas that is burned);
-- at the first block of an epoch it jumps (new NEAR minted for validators). So the block-to-block
-- change splits cleanly into minted (rises) and burned (falls).
-- Cost control: filters on block_date and reads 5 columns.
WITH b AS (
SELECT
block_date,
block_height,
block_timestamp,
gas_price,
total_supply,
total_supply - LAG(total_supply) OVER (ORDER BY block_height) AS delta
FROM `bigquery-public-data.crypto_near_mainnet_us.blocks`
WHERE block_date BETWEEN DATE_SUB(@from_date, INTERVAL 1 DAY) AND @to_date
)
SELECT
block_date,
COUNT(*) AS blocks,
MIN(block_height) AS first_height,
MAX(block_height) AS last_height,
SAFE_DIVIDE(MAX(block_timestamp) - MIN(block_timestamp), 1e9 * (COUNT(*) - 1)) AS seconds_per_block,
MIN(gas_price) AS min_gas_price,
MAX(gas_price) AS max_gas_price,
COUNTIF(gas_price > 100000000) AS blocks_above_floor,
SUM(IF(delta > 0, delta, 0)) AS minted_yocto,
SUM(IF(delta < 0, -delta, 0)) AS burned_yocto,
COUNTIF(delta > 0) AS mint_blocks,
ARRAY_AGG(total_supply ORDER BY block_height DESC LIMIT 1)[OFFSET(0)] AS end_supply_yocto
FROM b
WHERE block_date BETWEEN @from_date AND @to_date
GROUP BY block_date
ORDER BY block_dateWho fills the blocks
In the week before 2 April 2026 one app, Kaiching, burned 63% of all gas. Today the largest account is intents.near with 12%, and no group has more than 28%.
The query
analyze.py: accounts are grouped into apps by name with the rules in data/labels.json (exact names, then suffixes).
-- sql/04_gas_by_account.sql
-- Headroom 04: who fills the blocks. Gas burned per executing account over one window.
-- Every receipt and transaction has an execution outcome; executor_account_id is the account
-- whose code (or whose transaction) burned the gas. Accounts below 0.01% of the window's gas
-- are folded into one row so the file stays small.
-- Cost control: filters on block_date and reads 3 columns. Run it on short windows only.
WITH g AS (
SELECT executor_account_id AS account, SUM(gas_burnt) AS gas, COUNT(*) AS outcomes,
COUNTIF(status LIKE '%FAILURE%') AS failed
FROM `bigquery-public-data.crypto_near_mainnet_us.execution_outcomes`
WHERE block_date BETWEEN @from_date AND @to_date
GROUP BY 1
), t AS (SELECT SUM(gas) AS total FROM g)
SELECT
IF(g.gas >= 0.0001 * t.total, g.account, '(all other accounts)') AS account,
SUM(g.gas) AS gas_burnt,
SUM(g.outcomes) AS outcomes,
SUM(g.failed) AS failed_outcomes,
COUNT(*) AS accounts
FROM g CROSS JOIN t
GROUP BY 1
ORDER BY gas_burnt DESCNEAR Intents moves a lot of money through very little blockspace
In the latest week NEAR Intents settled $130M of swaps a day and its contracts burned 1.22M Tgas a day: 9,350 Tgas, or 0.83 NEAR, per $1M swapped. For its gas alone to cancel new NEAR at 1.6% it would need $68.8B a day, 528 times today. Intents helps NEAR's value through its fees, not its gas.
The query
analyze.py: Intents gas = the week's gas x the share of accounts grouped as NEAR Intents (intents.near and its *.omft.near / *.omdep.near tokens, data/labels.json). Volume = the same 7 days from DefiLlama's public API (api.llama.fi/summary/dexs/near-intents), pipeline/fetch_intents.py. The Explorer API cross-check runs only with a partner token.
-- sql/04_gas_by_account.sql
-- Headroom 04: who fills the blocks. Gas burned per executing account over one window.
-- Every receipt and transaction has an execution outcome; executor_account_id is the account
-- whose code (or whose transaction) burned the gas. Accounts below 0.01% of the window's gas
-- are folded into one row so the file stays small.
-- Cost control: filters on block_date and reads 3 columns. Run it on short windows only.
WITH g AS (
SELECT executor_account_id AS account, SUM(gas_burnt) AS gas, COUNT(*) AS outcomes,
COUNTIF(status LIKE '%FAILURE%') AS failed
FROM `bigquery-public-data.crypto_near_mainnet_us.execution_outcomes`
WHERE block_date BETWEEN @from_date AND @to_date
GROUP BY 1
), t AS (SELECT SUM(gas) AS total FROM g)
SELECT
IF(g.gas >= 0.0001 * t.total, g.account, '(all other accounts)') AS account,
SUM(g.gas) AS gas_burnt,
SUM(g.outcomes) AS outcomes,
SUM(g.failed) AS failed_outcomes,
COUNT(*) AS accounts
FROM g CROSS JOIN t
GROUP BY 1
ORDER BY gas_burnt DESCThe day one app left
When Kaiching stopped on 2 April 2026, NEAR lost 71% of its gas and 76% of its transactions overnight, but only 4% of its active accounts. Counting accounts would have missed it.
The query
analyze.py: each series divided by its value on 9 March 2026.
-- sql/01_chunks_daily.sql
-- Headroom 01: NEAR blockspace per day and shard.
-- gas_limit is what the chain could have processed, gas_used is what it did process.
-- One row per (day, shard). A chunk is one shard's slice of one block.
-- Cost control: filters on block_date (the partition column) and reads 4 small columns.
SELECT
block_date,
shard_id,
COUNT(*) AS chunks,
SUM(gas_used) AS gas_used,
SUM(gas_limit) AS gas_limit,
COUNTIF(gas_used >= 0.5 * gas_limit) AS chunks_over_half,
COUNTIF(gas_used >= 0.8 * gas_limit) AS chunks_over_80pct,
MAX(SAFE_DIVIDE(gas_used, gas_limit)) AS max_fill
FROM `bigquery-public-data.crypto_near_mainnet_us.chunks`
WHERE block_date BETWEEN @from_date AND @to_date
GROUP BY block_date, shard_id
ORDER BY block_date, shard_id
-- sql/03_daily_counts.sql
-- Headroom 03: transactions and receipts per day, read from table metadata.
-- INFORMATION_SCHEMA.PARTITIONS holds the row count of each daily partition, so this
-- costs the 10 MB minimum instead of scanning billions of rows.
SELECT
table_name,
PARSE_DATE('%Y%m%d', partition_id) AS block_date,
total_rows
FROM `bigquery-public-data.crypto_near_mainnet_us.INFORMATION_SCHEMA.PARTITIONS`
WHERE table_name IN ('transactions', 'receipt_details')
AND REGEXP_CONTAINS(partition_id, r'^\d{8}$')
AND PARSE_DATE('%Y%m%d', partition_id) BETWEEN @from_date AND @to_date
ORDER BY table_name, block_date
-- sql/05_active_accounts_daily.sql
-- Headroom 05: daily active accounts (distinct transaction signers) and transactions.
-- Used to compare "people-style" usage numbers with paid usage (gas).
-- Cost control: filters on block_date and reads one string column; kept to the last 13 months.
SELECT
block_date,
COUNT(DISTINCT signer_account_id) AS active_accounts,
COUNT(*) AS transactions
FROM `bigquery-public-data.crypto_near_mainnet_us.transactions`
WHERE block_date BETWEEN @from_date AND @to_date
GROUP BY block_date
ORDER BY block_dateAccounts and gas tell different stories
Daily active accounts fell 74% from October 2025 to October 2026, and paid gas 70% over the year to 2026-11-12. Gas is the one that costs money to fake.
The query
analyze.py: both series divided by their value on 1 October 2025.
-- sql/05_active_accounts_daily.sql
-- Headroom 05: daily active accounts (distinct transaction signers) and transactions.
-- Used to compare "people-style" usage numbers with paid usage (gas).
-- Cost control: filters on block_date and reads one string column; kept to the last 13 months.
SELECT
block_date,
COUNT(DISTINCT signer_account_id) AS active_accounts,
COUNT(*) AS transactions
FROM `bigquery-public-data.crypto_near_mainnet_us.transactions`
WHERE block_date BETWEEN @from_date AND @to_date
GROUP BY block_date
ORDER BY block_date
-- sql/01_chunks_daily.sql
-- Headroom 01: NEAR blockspace per day and shard.
-- gas_limit is what the chain could have processed, gas_used is what it did process.
-- One row per (day, shard). A chunk is one shard's slice of one block.
-- Cost control: filters on block_date (the partition column) and reads 4 small columns.
SELECT
block_date,
shard_id,
COUNT(*) AS chunks,
SUM(gas_used) AS gas_used,
SUM(gas_limit) AS gas_limit,
COUNTIF(gas_used >= 0.5 * gas_limit) AS chunks_over_half,
COUNTIF(gas_used >= 0.8 * gas_limit) AS chunks_over_80pct,
MAX(SAFE_DIVIDE(gas_used, gas_limit)) AS max_fill
FROM `bigquery-public-data.crypto_near_mainnet_us.chunks`
WHERE block_date BETWEEN @from_date AND @to_date
GROUP BY block_date, shard_id
ORDER BY block_date, shard_idSince 4 November, gas burns more
Block 223,012,337 (2026-11-04 11:46 UTC) ended the 30% gas rebate to contract developers. The share of the gas bill that is destroyed went from 76% to 89%. The rest is refunds, which run at a gas price of zero (22% of all gas on 10 Nov).
The query
analyze.py: burned (fall in total supply) / (gas_used x 1e8). The rule change itself is read from the protocol config at blocks 223,012,336 and 223,012,337 (pipeline/fetch_rpc.py, data/raw/rpc/protocol.json).
-- sql/02_blocks_daily.sql
-- Headroom 02: gas price and total supply per day.
-- Every block header carries total_supply. Inside an epoch it only falls (gas that is burned);
-- at the first block of an epoch it jumps (new NEAR minted for validators). So the block-to-block
-- change splits cleanly into minted (rises) and burned (falls).
-- Cost control: filters on block_date and reads 5 columns.
WITH b AS (
SELECT
block_date,
block_height,
block_timestamp,
gas_price,
total_supply,
total_supply - LAG(total_supply) OVER (ORDER BY block_height) AS delta
FROM `bigquery-public-data.crypto_near_mainnet_us.blocks`
WHERE block_date BETWEEN DATE_SUB(@from_date, INTERVAL 1 DAY) AND @to_date
)
SELECT
block_date,
COUNT(*) AS blocks,
MIN(block_height) AS first_height,
MAX(block_height) AS last_height,
SAFE_DIVIDE(MAX(block_timestamp) - MIN(block_timestamp), 1e9 * (COUNT(*) - 1)) AS seconds_per_block,
MIN(gas_price) AS min_gas_price,
MAX(gas_price) AS max_gas_price,
COUNTIF(gas_price > 100000000) AS blocks_above_floor,
SUM(IF(delta > 0, delta, 0)) AS minted_yocto,
SUM(IF(delta < 0, -delta, 0)) AS burned_yocto,
COUNTIF(delta > 0) AS mint_blocks,
ARRAY_AGG(total_supply ORDER BY block_height DESC LIMIT 1)[OFFSET(0)] AS end_supply_yocto
FROM b
WHERE block_date BETWEEN @from_date AND @to_date
GROUP BY block_date
ORDER BY block_date
-- sql/06_free_gas_day.sql
-- Headroom 06: how much of the gas NEAR burns pays nothing, on one day.
-- Refunds run as receipts with a gas price of zero, so their gas is counted in gas used but
-- burns no NEAR. Paid outcomes can burn a little more than gas x price (refund penalty).
-- Cost control: one day, two numeric columns.
SELECT
@from_date AS block_date,
COUNT(*) AS outcomes,
COUNTIF(tokens_burnt = 0) AS free_outcomes,
SUM(gas_burnt) AS gas_burnt,
SUM(IF(tokens_burnt = 0, gas_burnt, 0)) AS free_gas_burnt,
SUM(tokens_burnt) AS tokens_burnt_yocto
FROM `bigquery-public-data.crypto_near_mainnet_us.execution_outcomes`
WHERE block_date BETWEEN @from_date AND @to_dateThe break-even model
Move the sliders. Burn per Tgas is measured on chain since the rebate ended (89.3 NEAR per million Tgas). Capacity is today's 10 shards; NEAR can add shards, which raises capacity but not the break-even amount of gas.
Will it fit? A capacity check for builders
Enter your app's expected load. Presets are real transactions read from mainnet; or paste any transaction to measure it.
Declared demand, from near.social
Posts tagged #headroom with a line like load: 500,000 tx/day x 8 Tgas. Read live from the near.social
indexer; each author's account is checked on a NEAR node. A declaration is a promise, not usage: compare it with the meter above.
A near.social post is itself a NEAR transaction: the median of five measured posts burned 1.43 Tgas, so today's capacity could carry
about 12,097 posts a second.
Six signals that can prove this wrong
Each is recomputed by python rebuild.py. Today 4 of 6 pass. The thesis turns positive when S4 passes for four quarters in a row; S3 shows how far there is still to go.
| S1 | Headroom exists 30-day utilization under 10% | 0.72% | passes | There is room to grow at today's fees. If this fails, NEAR is filling up and fees will start to move. |
| S2 | Fees are flat gas price at the floor in 99.9% of blocks since May 2024 | 99.9999% | passes | Builders can price their product in advance. If this fails, a fee market has started. |
| S3 | Burn covers new NEAR 30-day burn at least 25% of NEAR minted | 0.93% | fails | The value case through gas. It fails today by a wide margin. |
| S4 | Paid demand is growing 30-day gas used above the same 30 days a year earlier | -70% | fails | The thesis needs paid gas to grow 61-fold: 51% a year for ten years. It fails today. |
| S5 | No single customer no account burns more than 25% of a week's gas | 12.3% (intents.near) | passes | In March 2026 one app burned 63% of all gas and then left. Today it passes. |
| S6 | Cheap for users average fee per transaction under $0.01 | $0.0047 | passes | Low fees are what the headroom buys. If this fails at the floor price, NEAR's price has run far ahead of usage. |
Method and sources
- Blockspace: every chunk since July 2020 from the NEAR BigQuery dataset
bigquery-public-data.crypto_near_mainnet_us(tableschunks,blocks,execution_outcomes,transactions), always filtered onblock_date. All queries together scanned about 97 GB. - Rules: the gas rebate, the issuance cap and the protocol version are read from NEAR's own protocol config at chosen blocks on an archival node.
- Burn: measured as the fall in total supply between blocks, not computed from a formula.
- Price: DefiLlama's public price API, used only to show dollars.
- near.social: the public indexer
api2.near.social; posts are FastData transactions to the accountsocial.
Not measured: NEAR Intents swap volume (the Explorer API needs a partner token; see THESIS.md) and the people behind accounts. The full claim, the evidence for and against, and what would change our mind are in THESIS.md.