Here is the trap with monitoring a blockchain node: the obvious check passes when the node is broken.
You point a standard uptime monitor at your node's RPC endpoint. It sends a request, gets back HTTP 200, and reports the node as "up." Green dashboard, no alerts. Meanwhile the node has been stuck on the same block for two hours, is still syncing and returning stale data, or is answering every call with an error object buried inside a perfectly valid-looking JSON response. Everything depending on that node is failing — and your monitoring is happy.
This guide is about closing that gap: why a status-code check is misleading for RPC endpoints, what you actually need to verify, and how to monitor a JSON-RPC or blockchain node so that "up" means usable.
A JSON-RPC endpoint — whether it's an Ethereum execution client, a Solana validator's RPC, a Bitcoin Core node, or any other chain — is an HTTP server sitting in front of the node software. A plain uptime check only talks to that HTTP layer. And the HTTP layer will cheerfully return 200 OK in all of these broken states:
error object — with an HTTP 200 around it. A status-code check never looks inside the body, so it never sees the error.In every case, the surface check — "did the server respond 200?" — gives the wrong answer. The information you need is inside the JSON, and you only get it by sending a real RPC call and reading the response.
Three checks, in increasing order of how much they tell you. A good node monitor does all three.
Send a real JSON-RPC request — a POST with a proper JSON body — and confirm the response is well-formed JSON containing a result, not an error object. This alone is a big step up from a status-code check: it catches malformed responses and JSON-RPC-level errors that a 200 would hide.
A minimal Ethereum-style request to fetch the current block number looks like this:
Different chains use different methods — Solana's RPC has getSlot and getHealth, Bitcoin Core has getblockchaininfo — but the shape is the same: send a real call, require a result, reject an error.
This is the check that catches a stalled node, and it's the one almost nothing does by default. A single call tells you the node responded; it can't tell you the node is keeping up. To know that, you have to compare across time: record the block height (or slot) on each check and confirm it has increased since the previous one.
Be aware this is genuinely hard to do with an off-the-shelf monitor. Most uptime tools — failover.io included — evaluate each check in isolation: they can assert that a value in the response is above a fixed threshold, but they don't remember the previous check's value to compare against it. That means a monitoring tool can catch a height that's below an absolute number you set, but not a height that's simply frozen while still above that number.
There are two practical ways to handle the frozen-height case. The simple one: set an absolute threshold and bump it periodically — crude, but it catches a node that has fallen badly behind. The proper one: run a small script (a cron job, a serverless function) that calls the node, stores the height, compares it to the stored value from last time, and fails — or pings a heartbeat monitor — if it hasn't moved. The script owns the stateful comparison; your monitoring tool owns the alerting. A frozen height is one of the clearest health signals a node gives you, so it's worth the small amount of glue code.
Most clients expose their own sync state. Ethereum execution clients answer eth_syncing — it returns false when fully synced, or an object describing progress when not. Solana has getHealth. Bitcoin Core reports verification progress in getblockchaininfo. Querying the node's own view of itself catches the "up but serving stale data because it's still catching up" case directly.
| Check | Catches | Misses if skipped |
|---|---|---|
| HTTP 200 only | Server / port down | Everything below |
| Valid RPC result | JSON-RPC errors, malformed responses | Stalled & syncing nodes |
| Height vs absolute threshold | Node fallen badly behind | A frozen height still above the threshold |
| Height delta (needs a script) | Stalled node, lost consensus | — |
| Sync-state check | Node serving stale data while catching up | — |
To run the checks above, a monitoring tool has to be able to do things a basic uptime checker often can't:
GET can't make a real RPC call at all.result exists, that error does not, ideally that a value matches an expected pattern.POST with a dedicated request-body field — it ships with a JSON-RPC call as the placeholder example — and up to 20 custom headers per monitor for authenticated endpoints. Its body assertions inspect the response so a JSON-RPC error object, a missing result, or a height below a threshold you set is treated as a failure rather than a pass. One honest limit: those assertions evaluate each response on its own, so for true frozen-height detection you'd still pair it with the small script described above, using a heartbeat monitor as the alert target. Paired with failover.io's escalation chains, a failing node triggers the same climb to SMS and voice call as any other outage. The free plan covers 5 monitors — start free.
Putting it together, a solid setup for a single RPC node looks like this:
eth_blockNumber, getSlot, or your chain's equivalent — including any required auth headers.result field and fails on an error object.A blockchain node can return HTTP 200 and still be useless — stalled, syncing, or returning a JSON-RPC error inside a valid-looking response. Monitoring a node properly means treating it as a correctness check, not a connectivity check: send a real RPC call, require a valid result in the body, watch the block height (against a threshold in your monitor, and with a small script for true frozen-height detection), and read the node's own sync state. That requires a monitor that can POST a custom JSON body, send auth headers, and assert on the response body — and, as always, an escalation path so that when the node degrades, a human actually finds out.
failover.io: first-class JSON-RPC checks, body assertions, and escalation that climbs until someone acknowledges. Free plan, no credit card.
Start monitoring free →