Data access · 10 min read

Monad onchain data: 94 million blocks, and every time the chain retuned itself

Monad mainnet has produced 94 million blocks since May 2025. Three times in that history the chain changed its own block time or its own gas limit, and every one of those changes is recorded in the block headers. This page finds all three, dates them, and reads what they were for.

Nothing here comes from an announcement or a changelog. It is the header fields, read from block 0 to the head, from portal.sqd.dev/datasets/monad-mainnet, a public dataset.

Updated 2026-08-28 · By the SQD team

1. Starting at block 0, including the strange one

The dataset starts at block 0, so there is no gap between genesis and the head to work around. Ask for the first two blocks:

your terminal
curl -s https://portal.sqd.dev/datasets/monad-mainnet/stream \
-H 'content-type: application/json' \
-d '{
"type": "evm",
"fromBlock": 0,
"toBlock": 1,
"includeAllBlocks": true,
"fields": { "block": { "number": true, "timestamp": true, "gasLimit": true } }
}'
{"header":{"number":0,"timestamp":0,"gasLimit":"0x1388"}}
{"header":{"number":1,"timestamp":1747232689,"gasLimit":"0x8f0d180"}}

Block 0 carries timestamp 0 and gasLimit 0x1388, which is 5,000. Those are genesis placeholders, not measurements, and they are worth knowing about before you build anything on top: a block-time average that includes block 0 computes against the Unix epoch and returns a number 55 years wrong. Start at block 1.

Block 1 is timestamp 1747232689, which is 2025-05-14 14:24:49 UTC, and its gas limit is 0x8f0d180, 150,000,000. That is the real start of the chain and the baseline for everything below.

2. Three times the chain changed its own numbers

Sampling the header at 25 points across the 94 million blocks shows two fields that are not constant: gasLimit and, indirectly, the interval between timestamps. Bisecting on each gives this.

FromBlockBlock timeGas limitCapacity
  • 2025-05-1410.50 s150,000,000300M gas/s
  • 2025-08-13~15,597,0000.40 s150,000,000375M gas/s
  • 2025-11-0433,442,4870.40 s200,000,000500M gas/s
  • 2026-07-2389,656,7350.30 s150,000,000500M gas/s
Every parameter change in Monad's mainnet history, read from block headers. Capacity is the gas limit divided by the block time.

The gas-limit rows carry exact block numbers because gasLimit is a field, so a bisection lands on a single block. Block 33,442,486 reads 150,000,000 and block 33,442,487 reads 200,000,000, both stamped 2025-11-04 14:09:28 UTC.

The 2025-08-13 row does not, and the reason is worth stating rather than hiding behind a tilde. Block time is not a field, it is a rate between timestamps, and Monad's timestamps have one-second resolution while its blocks are twice a second or faster. Two adjacent blocks are either 0 or 1 second apart, which tells you nothing. You can only see the rate change across a window, and the best this method does is bracket it: the average is 0.5017 s/block up to block 15,596,138 and 0.4014 s/block from block 15,599,138, so the change is somewhere in the three thousand blocks between them, around 14:25 to 14:32 UTC. Anything more precise would be invented.

3. The block where two numbers moved at once

The most recent change is the interesting one, because both parameters moved together and the exact block is recoverable.

block 89,656,734 gasLimit 200,000,000 2026-07-23 14:35:11 UTC
block 89,656,735 gasLimit 150,000,000 2026-07-23 14:35:12 UTC
average block time, 3,000 blocks either side
89,653,735 .. 89,656,734 0.4008 s/block
89,656,735 .. 89,659,735 0.3033 s/block

At block 89,656,735 the gas limit drops by a quarter and the block rate rises by about a third, in the same block. Multiply them out:

Gas limitBlock timeGas per second
  • Before200,000,0000.4008 s499M
  • After150,000,0000.3033 s495M
Blocks 89,653,735 to 89,659,735, split at the upgrade.

Capacity per second is the same on both sides, within measurement noise. The chain did not gain or lose throughput that day; it moved the same throughput into smaller, more frequent blocks, cutting the wait for inclusion by about a quarter while leaving the amount of work per second alone.

Both levers moved a quarter; capacity per second did not

Averages over 3,000 blocks either side of block 89,656,735 (2026-07-23). Bars are normalized within each row.

Gas limit gas per block before · 200,000,000 after · 150,000,000 −25.0% Block time seconds per block 0.4008 s 0.3033 s −24.3% Capacity gas per second 499M 495M −0.8%
Blocks 89,653,735-89,659,735 Source: SQD Portal · monad-mainnet · 2026-08-28

For anyone reading this chain, that combination matters more than either number on its own. A per-block gas budget that shrank by 25% means a transaction that used to fit may not, while a shorter block time means more blocks to scan for the same wall-clock window. Watching only gasLimit would have shown a capacity cut that did not happen.

4. What the capacity was for

Capacity changes are easier to read next to demand. Counting every transaction in a 10,000-block sample at intervals across the history:

BlockDateTransactionsPer block
  • 1,000,0002025-05-20170.00
  • 10,000,0002025-07-11330.00
  • 20,000,0002025-09-03160.00
  • 25,000,0002025-09-261,7530.18
  • 30,000,0002025-10-192,6510.27
  • 35,000,0002025-11-1113,3711.34
  • 40,000,0002025-12-0579,9437.99
  • 50,000,0002026-01-2077,2197.72
  • 60,000,0002026-03-0870,8437.08
  • 70,000,0002026-04-2396,0079.60
  • 80,000,0002026-06-08124,29412.43
  • 88,000,0002026-07-15147,50514.75
  • 94,400,0002026-08-09124,13912.41
Transactions per 10,000 consecutive blocks, sampled across Monad's history.

The chain ran for about four months at effectively zero traffic, a few dozen transactions per ten thousand blocks, then activity began around block 25,000,000 in late September 2025 and has climbed since. The first capacity increase, the block-time cut in August 2025, landed before any of it. The second, the gas-limit raise on 2025-11-04, landed while per-block traffic was going through 1.34 and about to reach 8.

Four near-empty months, then a climb to 14.75 per block
Transactions per block, 13 samples of 10,000 consecutive blocks across the history
12.41
per block at block 94,400,000
5 10 15 12.41 14.75 12.41 May 25 Sep 25 Dec 25 Apr 26 Aug 26

Definition. Each bar is one sample: every transaction in the 10,000 consecutive blocks starting at the labeled block, divided by 10,000. Samples are evenly spaced in block height, not in time.

Data: SQD Portal · monad-mainnet As of 2026-08-09

Two 20,000-block sweeps give the fuller picture at either end of 2026. At block 60,000,000 in March: 134,962 transactions, 6.75 per block, 16.9 per second, using 1.42% of the block gas limit. At block 94,000,000 in August: 266,722 transactions, 13.34 per block, 44.2 per second, 7.00% of the limit. Throughput roughly doubled in five months, and the chain still uses a single-digit share of the capacity its headers advertise.

5. Reproduce it

This reads the 6,001 blocks around the upgrade, groups them by the gas limit in their header, and prints the block time and the resulting capacity for each group. It is the whole of section 3 in one file.

monad.mjs
import { evmPortalStream, evmQuery } from '@subsquid/pipes/evm'
// The upgrade sits at block 89,656,735. Read 3,000 blocks either side of it.
const UPGRADE = 89_656_735
const FROM = UPGRADE - 3_000
const TO = UPGRADE + 3_000
const stream = evmPortalStream({
id: 'monad-parameter-history',
portal: 'https://portal.sqd.dev/datasets/monad-mainnet',
outputs: evmQuery()
.addFields({ block: { number: true, timestamp: true, gasLimit: true } })
.addLogRequest({ range: { from: FROM, to: TO }, request: {} })
.build(),
})
const eras = new Map()
let seen = 0
for await (const { data } of stream) {
for (const block of data) {
seen++
const limit = BigInt(block.header.gasLimit).toString()
const era = eras.get(limit) ?? { first: block.header, last: block.header, n: 0 }
era.last = block.header
era.n++
eras.set(limit, era)
}
}
// Portal returns only blocks with matching data, so prove none were skipped:
console.log(`coverage ${seen} of ${TO - FROM + 1} blocks`)
for (const [limit, era] of eras) {
const span = era.last.timestamp - era.first.timestamp
const blocks = era.last.number - era.first.number
const blockTime = span / blocks
console.log(
`gasLimit ${Number(limit).toLocaleString().padStart(11)} ` +
`blocks ${era.first.number.toLocaleString()}..${era.last.number.toLocaleString()} ` +
`${blockTime.toFixed(4)} s/block ` +
`${(Number(limit) / blockTime / 1e6).toFixed(0)}M gas/s`
)
}

Output, on @subsquid/pipes 1.0.0-beta.1:

coverage 6001 of 6001 blocks
gasLimit 200,000,000 blocks 89,653,735..89,656,734 0.4008 s/block 499M gas/s
gasLimit 150,000,000 blocks 89,656,735..89,659,735 0.3033 s/block 495M gas/s

Two groups, one boundary, and the capacity figures land four million gas per second apart on either side of a change that moved both inputs. Nothing in the script knows the upgrade happened; it falls out of grouping the headers.

The coverage line is not decoration. By default Portal returns only blocks with matching data, and an empty logs filter matches every log, not every block. In this window every block carries at least one log, which the script proves by counting what it received against the full range; a header-only block would have made that line read short instead of silently shrinking an era.

6. Why this needs the whole history

Every finding on this page is a header field, which is the cheapest data a chain has. The difficulty is not the fields, it is needing all 94 million of them.

Bisecting for each gas-limit change took about two dozen single-block reads, which any endpoint can serve. Establishing that there were exactly two such changes did not: that came from sampling the full range first, and a sample that misses a window misses a change entirely. The 2025-08-13 block-time cut is invisible in any single block and only appears when you can average across arbitrary windows on demand, cheaply enough to do it repeatedly while narrowing down.

That is the shape of the problem: not one expensive query, but hundreds of cheap ones spread across fifteen months of history, where each answer decides the next question. Over an archive node this is a project. Against a dataset that starts at block 0 it is an afternoon.

The same request shape runs against every network Portal serves, so the sampling above is one word away from any other chain. The blockchain data API guide covers the request format itself, including the continuation behaviour the sampling here relies on.

Frequently asked questions

What is Monad's block time?
About 0.30 seconds today, and it has changed twice. Measured from block headers: 0.50 s/block from the first block on 2025-05-14, 0.40 s/block from 2025-08-13, and 0.30 s/block from block 89,656,735 on 2026-07-23. Each figure is an average over thousands of consecutive blocks, because Monad block timestamps have one-second resolution while blocks are faster than that, so no single pair of blocks tells you the rate.
What is Monad's gas limit?
150,000,000 per block today. It has been changed twice, and both changes are visible in the headers to the exact block: raised from 150,000,000 to 200,000,000 at block 33,442,487 on 2025-11-04, then lowered back to 150,000,000 at block 89,656,735 on 2026-07-23. The second change landed in the same block as the block-time cut, which kept capacity per second roughly constant at about 500 million gas.
When did Monad mainnet launch?
Block 1 carries timestamp 1747232689, which is 2025-05-14 14:24:49 UTC. Block 0 exists in the dataset but carries a timestamp of 0 and a gas limit of 5,000, the usual genesis placeholder values, so any block-time calculation that starts from block 0 will be wrong. Start from block 1.
How many transactions per second does Monad do?
Measured over 20,000 consecutive blocks at block 94,000,000 (2026-08-07): 266,722 transactions, which is 13.34 per block and 44.2 per second. That is roughly 7% of the block gas limit in use. The same measurement at block 60,000,000 in March 2026 gave 6.75 transactions per block and 16.9 per second, so throughput roughly doubled over five months.
How do I index Monad from genesis?
SQD Portal serves monad-mainnet as a public dataset with start_block 0, so the full history is queryable without running an archive node. A request states a fromBlock and a toBlock and returns newline-delimited JSON; a response covers as much of the range as fits, and you resume from the last block it returned. The Pipes SDK wraps the same endpoint with typed queries and handles the continuation for you.

Reading a chain from genesis

monad-mainnet is a public dataset on Portal, from block 0 to the head.