Guides / Monitoring
Monitoring

How to Monitor a JSON-RPC or Blockchain Node's Uptime

Last updated May 2026 · ~9 min read

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.

Why HTTP 200 lies about node health

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:

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.

The core principle. Monitoring a blockchain node is not a connectivity check, it's a correctness check. "Is the port open" is necessary but nowhere near sufficient. The real question is "is this node returning current, valid data right now" — and answering it means inspecting the body of a genuine JSON-RPC response, not just its status code.

What to actually check

Three checks, in increasing order of how much they tell you. A good node monitor does all three.

1. The RPC call succeeds and the body is valid

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:

# POST to the RPC endpoint, JSON body: { "jsonrpc": "2.0", "method": "eth_blockNumber", "params": [], "id": 1 } # Healthy response — note result is a hex string: { "jsonrpc": "2.0", "id": 1, "result": "0x14a2f3c" } # Unhealthy — HTTP 200, but an error object in the body: { "jsonrpc": "2.0", "id": 1, "error": { "code": -32000, "message": "..." } }

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.

2. The block height is advancing

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.

3. The node doesn't report itself as syncing

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.

CheckCatchesMisses if skipped
HTTP 200 onlyServer / port downEverything below
Valid RPC resultJSON-RPC errors, malformed responsesStalled & syncing nodes
Height vs absolute thresholdNode fallen badly behindA frozen height still above the threshold
Height delta (needs a script)Stalled node, lost consensus
Sync-state checkNode serving stale data while catching up

The practical requirements for your monitoring tool

To run the checks above, a monitoring tool has to be able to do things a basic uptime checker often can't:

How failover.io handles RPC monitoring. failover.io is built for this kind of check rather than bending a plain HTTP monitor to fit. A monitor can use 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.

A sensible monitoring setup for a node

Putting it together, a solid setup for a single RPC node looks like this:

  1. A POST monitor hitting the RPC endpoint with a real call — eth_blockNumber, getSlot, or your chain's equivalent — including any required auth headers.
  2. A body assertion that requires a result field and fails on an error object.
  3. A short check interval — frequent enough that a frozen block height shows up within minutes.
  4. Block-height tracking so a stalled-but-responding node is caught — an absolute-threshold assertion for a node that has fallen far behind, plus the small height-delta script described above for a truly frozen one.
  5. An escalation chain on the monitor so a real problem reaches a human — see the companion guide on alert escalation for solo developers and small teams.
  6. If you run more than one node, monitor each independently — a load balancer in front can mask one bad node behind the healthy ones.

The short version

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.


Monitor your node properly.

failover.io: first-class JSON-RPC checks, body assertions, and escalation that climbs until someone acknowledges. Free plan, no credit card.

Start monitoring free →