Accurate sync check for Monad nodes.
Sync status is harder to measure cleanly than it looks: a height-vs-height query against a remote RPC bakes in network RTT, and at Monad's ~500ms block time even a few hundred ms of latency shifts the answer you see. monad-bench cross-checks three signals — NTP-anchored timestamp, drift trend, and RTT-corrected height — so the verdict holds up regardless of where in the world you're running from.
curl -sSL https://rustemar.dev/monad-bench.sh | bashmonad-bench # 10 samples, summary only
monad-bench 30 # 30 samples
monad-bench 30 -v # 30 samples, verbose (per-sample output)=== ntp ===
chrony source=(64.130.55.174) stratum=3 offset=0.0ms status=Normal
=== bench ===
samples: 15
local: http://localhost:8080
ext: https://rpc-testnet.monadinfra.com
---
=== timestamp ===
lag min=0.33s max=1.26s med=0.81s avg=0.79s
note: 0-2s is normal chain propagation
=== trend ===
window: 1.0s, 15 samples
1st-half avg=0.90s 2nd-half avg=0.70s drift=-0.20s
block rate: 3.00 blk/s (expected 2.00)
trend: stable
=== comparison ===
latency avg=58ms (local=3ms ext=54ms)
RTT/2 correction: 27ms (~0.05 blocks)
diff raw min=0 max=1 med=0 avg=0.07
diff corr avg=0.01
dist diff=0: 14/15 (93%) diff=1: 1/15 diff>1: 0/15 diff<0: 0/15
=== verdict ===
timestamp: fully synced (avg 0.79s)
trend: stable (drift -0.20s)
comparison: synced (corrected avg 0.01)
OK: all checks passed
ran 15 samples over 1.0s
Three independent methods so no single blind spot ruins the answer:
| method | what it does | why it matters |
|---|---|---|
| timestamp | compares the latest block's timestamp to the system clock (NTP) | no network involved — immune to RTT |
| trend | compares 1st-half vs 2nd-half avg lag across the test window | detects whether the node is falling behind |
| comparison | local vs official RPC block height, corrected by ext_latency/2 |
sanity-checks against the rest of the world |
A healthy node: timestamp ≤ 2s, trend stable, comparison ≈ 0. A 0–2s timestamp lag is normal chain propagation — not a problem.
| code | meaning |
|---|---|
| 0 | healthy |
| 1 | warning (lag growing, or node behind) |
| 2 | review needed (mixed signals) |
| 3 | RPC error (node unreachable / bad data) |
Useful for cron and monitoring.
bash,curl,jq,awk- An NTP service for the timestamp check:
chrony(preferred),ntpd, orsystemd-timesyncd. The script tells you how to installchronyif none is found.
A single height-vs-height query mixes two things: how far the node is actually behind, and how long the reply took to arrive. The reply traverses one-way latency, during which the chain keeps moving. From Japan to a European RPC that's ~235 ms — against a 500 ms block time, roughly half a block of geographic offset per sample, independent of node health.
monad-bench separates these by (a) anchoring the primary check to the
local clock via NTP, so no network sits in the loop, and (b) applying an
ext_latency / 2 correction to the secondary height comparison. The
third check — drift across the window — catches the case where individual
samples look fine but the gap is widening over time.
MIT — see LICENSE.