By Nika, NodeTimes newsroom.
Blockchain RPC is the client-server interface an application uses to read chain state from a node or hand it a transaction; on Ethereum-family chains it speaks JSON-RPC. The node does the work; the endpoint is only the address you send calls to. Every balance and every confirmation a wallet shows you is the answer to one of those calls, which is why the honesty of that single hop is the honesty of the application.
What RPC means in a blockchain context
RPC (remote procedure call) lets one program invoke a procedure that runs on another machine; in a blockchain the caller is a wallet, a bot or a backend, and the callee is a node. The protocol is deliberately plain: an HTTP POST carrying JSON, a method name, parameters and an ID.
JSON-RPC: the protocol they speak, a stateless and transport-agnostic call format that carries JSON, so the same request works over HTTP, a WebSocket or an in-process socket. Execution client: the node software that executes transactions, maintains the state trie and answers JSON-RPC (Geth, Nethermind, Besu, Erigon, Reth). Consensus client: a separate process that follows the beacon chain and drives the execution client over the Engine API (a node-local channel, not an internet-facing endpoint).
The request shapes, as the specification defines them:
{"jsonrpc":"2.0","id":1,"method":"eth_getBalance","params":["0x…","latest"]}
{"jsonrpc":"2.0","id":2,"method":"eth_chainId","params":[]}
The namespaces you meet in production are few:
-
eth_*reads and writes chain state and transactions:eth_blockNumber,eth_getBalance,eth_getStorageAt,eth_call,eth_sendRawTransaction. -
net_*andweb3_*give network identity and client information, the cheap checks you use for consistency. -
debug_*andtrace_*cover tracing and simulation, and they are usually disabled on public endpoints. -
eth_getProofreturns a Merkle proof for an account or a storage slot: the one call that lets you verify an answer instead of trusting it.
If these terms are new, the glossary of the hundred terms a Web3 stack runs on keeps the definitions; this section carries only what you need to read one call.
Node types, and what each one can answer
A node type is fixed by how much state and history the machine keeps, not by the interface it exposes. That is why two endpoints with identical-looking URLs can behave differently: they are backed by different classes of node.
| Node type | Keeps | Answers | Typical use |
|---|---|---|---|
| Light node | block headers | headers only: it asks a full node for state and verifies the answer by proof | mobile wallets, low-resource clients |
| Full node | the latest state, recent snapshots, and every block and transaction | current state, recent blocks | wallets, dApps, endpoint operators |
| Archive node | every historical state | historical state at any past block | analytics, explorers, tracing |
| Validator (validator client on a consensus client) | a full node plus validator keys | block proposals and attestations | staking, consensus duty |
| RPC-only node (Solana) | state, no consensus role | reads and relays calls | Solana fleets that serve queries only |
A validator needs a minimum of 32 ETH to activate, and after EIP-7251 the effective balance on a single validator can be consolidated up to 2,048 ETH. The role is its own subject, taken up in what consensus means for a chain.
The distinction that matters commercially is validator versus RPC service. On Solana a validator runs consensus and earns rewards while an RPC node only answers queries; on Ethereum the execution client answers calls with or without a validator attached. The three storage classes, from light to archive, follow Ethereum's own documentation; the validator is separate software attached to a consensus client, and the query-only node is a Solana role, not an Ethereum class. Which class of node an endpoint fronts also depends on how the chain splits state, covered under sharding.
Node, endpoint and provider are three different things
An endpoint is a network address, a node is the process doing the work, and a provider is the company operating a fleet behind many endpoints. Collapse the three and you can believe you run decentralised infrastructure while sending every request to a single URL.
- One node can sit behind several endpoints, and one endpoint can be a load balancer over a fleet.
- A provider endpoint is a shared front door: that is why archive requests fail on free tiers, and why self-hosting buys a node but not high availability.
- The three are separated by who owns the failure: your application owns the request, the provider owns the route, and the node owns the answer.
Above all three sits the wider stack: L0, L1 and L2 decide where state and data settle, an endpoint is how you reach them, and your dApp is just another client.
How a call travels, and where it can be refused
A call is executed against the local state of one node, so latency, freshness and censorship all depend on which node answers it.
- Your application POSTs a JSON-RPC request to the endpoint.
- A load balancer routes it to one node in the fleet.
- That node's execution client answers from local state, or returns an error if the method is disabled.
- For a write, the node validates the raw transaction and gossips it; inclusion in a block is the builder's decision.
- A node that has fallen behind the chain head still answers, and the answer still looks well-formed.
Design for three failures rather than one: rate limits under load, methods missing on your tier, and a stale head after a node drops out of sync. A lagging node does not announce itself; it answers in the same shape as a healthy one.
What a node is, and why a chain needs so many of them, has its own explainer: why a blockchain needs nodes. And if the base layer is new to you, start with what a blockchain is.
Why two providers can answer differently
Two providers can answer the same call differently because each fronts nodes at a different point of sync, with its own source of truth, and a stale answer is still well-formed. The disagreement is invisible until you go looking for it.
- Indexing lag: a provider's nodes can trail the chain head, so a read pinned to the latest block resolves against slightly older state.
- Reorganisations: a recent block can be replaced, and an answer that was correct a moment ago stops being correct.
- Different sources of truth: a fleet may be backed by archive nodes, snapshots or an internal cache, and the internals of provider fleets are not documented in public.
The fix is to stop comparing snapshots of the latest block. Pin reads to a block hash (EIP-1898) and compare against a second, independently operated source: that is the only way to tell a real disagreement from a timing artefact.
What the operator of your endpoint can see and do
Whoever answers the call can watch it, delay it, censor it, or return data that is well-formed and simply false. RPC is a trust boundary, not plumbing.
- One provider is one point of truth, whatever the protocol around it promises.
- Cross-checking two independent endpoints turns most silent corruption into a visible disagreement.
- Where value moves, prefer an answer you can verify to an answer you asked twice.
The boundary is not theoretical. The KelpDAO bridge exploit ran through poisoned RPC responses: no contract bug and no compromised signing key, just a verification service that trusted answers from nodes an attacker controlled. That exploit is its own subject; here it only marks where the trust boundary sits. What that leaves of a decentralisation claim is taken up in what Web3 means in practice.
How to audit an endpoint
Run these eight checks on any endpoint before you trust it in production, and always against a second, independently operated source.
- Chain identity: call
eth_chainIdandnet_version. A mismatch means the endpoint serves a chain you did not intend to query. - Head freshness: compare
eth_blockNumberagainst a second provider. A gap means the node is stale or the fleet is inconsistent. - Sync state: call
eth_syncing. Anything other than false means responses come from state behind the head. - State pinning: call
eth_getBalancewith a block object instead oflatest. An error means the block-hash form of the parameter is unsupported. - Archive depth: request a balance at a fixed historical block. A silent fallback to the latest state means archive queries are not really archive.
- Trace support: make one
debug_ortrace_call. An error means tracing is disabled on this tier. - Load behaviour: send 20
eth_blockNumbercalls in 2 seconds. Rate limiting shows up as errors or added latency. - Method coverage: request one method per namespace you rely on and compare the result with the published specification.
EIP-1898 is what makes the pinning check possible: a caller passes {"blockNumber": …} or {"blockHash": …} instead of "latest", with -32001 recommended when the block is not found and a distinct error raised when requireCanonical fails. Pinning to a hash is how you query state coherently across a reorganisation.
The request-and-error contract lives in the Ethereum JSON-RPC specification (EIP-1474) and the execution-apis repository, not on a provider's marketing page, which is where most RPC explainers stop.
Run the checks in this order and the question changes: not "does my endpoint work", but "can it lie to me, and would I notice".
Frequently asked questions
Is an RPC endpoint the same as a node?
No. The node is the software that holds state and executes calls, and the endpoint is the address your application connects to, which may front a whole fleet.
Treating the two as synonyms is how a single point of failure gets mistaken for a cluster.
Is blockchain RPC centralized?
The protocol is not; your access to it usually is, because most production applications read through a handful of commercial providers.
A chain's decentralisation limits what one bad RPC can steal on its own, but it does not protect an application that trusts a single answer source.
Do I need an archive node?
Only if you query historical state. A full node answers the latest and recent blocks; an archive query against a non-archive node fails or returns something else.
For most applications a provider's archive tier costs less than running one; for analytics and traces the usual path is a self-hosted archive plus a database.
Why does my transaction "disappear" after being sent?
Because the endpoint only relayed it: a raw transaction enters the mempool, propagates or does not, and is included by a builder, none of which the sending endpoint controls.
The fix is operational: re-broadcast through a second endpoint, track the hash, and prefer endpoints that expose transaction status.
Which RPC methods should be disabled in production?
Any namespace you do not use, and tracer namespaces by default: debug_ and trace_ are expensive and are the usual vector for resource exhaustion on an internet-facing node.
A strict allowlist of eth_ read methods plus eth_sendRawTransaction covers most applications.
Top comments (0)