- Category
- Operations
- Reading time
- 12 minutes
- Published
- Updated
Do you need an archive node for EVM RPC?
A request for an “archive RPC” often bundles several different needs: an old token balance, logs from genesis, a transaction trace, a receipt from years ago, or a Merkle proof at a past block. Those requests do not all depend on the same data, and an endpoint that serves one may fail another.
The practical question is therefore not simply “do we need an archive node?” It is “which historical methods must work, at what block depth, on which chain, and after failover?”
This guide separates historical state from block history, maps common EVM methods to their real storage requirements, and gives you a repeatable test for a self-hosted node or managed RPC endpoint.
What is the short answer?
You need archive-capable state access when the application asks what an account or contract looked like at an old block. Typical examples are an old balance, contract code, storage slot, nonce, or eth_call result. A pruned full node usually serves current and recent state but eventually discards older state according to its client and pruning profile.
You do not automatically need historical state merely because a request refers to an old block. Blocks, transactions, receipts, and logs are chain history, not world state. A node may retain them while pruning old state, or prune them independently. Tracing is another capability again: it depends on the client, enabled namespace, retained inputs, tracer, and replay limits.
Ethereum.org defines an archive node as an execution client configured to build an archive of historical states. Use that definition as the starting point, then qualify every other kind of history separately.
What is the difference between historical state and chain history?
EVM infrastructure stores several related but distinct data sets:
- Current and historical state: account balances, nonces, contract bytecode, and contract storage after a particular block.
- Blocks and transactions: headers, bodies, transaction lists, and transaction lookup indexes.
- Receipts and logs: execution outcomes and emitted events.
- Execution traces: a reconstruction of the calls, opcodes, state changes, or transfers produced while executing a transaction or block.
- Trie nodes and proofs: the authenticated data needed to build a proof such as the result of
eth_getProof.
Calling every one of these “archive data” is convenient marketing shorthand, but it hides operational differences. Geth, for example, exposes separate controls for state, transaction, log, and trie-node history. Its current archive-mode documentation notes that a path-based archive can retain historical flat state without retaining the historical trie nodes required for old Merkle proofs. Reth likewise documents archive, full, minimal, and custom pruning profiles with different retained histories.
This is also why a universal cutoff such as “older than 128 blocks requires archive” is unreliable. A Geth profile and a Reth full profile can retain different state windows, and operators can customize them. Ask for the actual earliest available data per method instead of inferring it from the word “full.”
Which EVM RPC methods usually need historical state?
The block parameter tells you more than the method name. The following methods query state and need the target block’s state to be available when you pass an old block number or hash:
eth_getBalanceeth_getCodeeth_getStorageAteth_getTransactionCounteth_calleth_getProof
The first five are the clearest archive-state test set. eth_getProof needs extra care because serving an old state value does not prove that the node retained the trie material needed to construct a historical proof. Geth’s path-based archive documentation explicitly requires historical trie-node retention for this case.
By contrast, these calls do not inherently query the world state:
eth_getBlockByNumberandeth_getBlockByHashread block history.eth_getTransactionByHashdepends on transaction data and a lookup index.eth_getTransactionReceiptreads receipt history.eth_getLogsfilters historical receipts and logs.
They can still fail for old blocks if the node or provider prunes that history. The current Ethereum Execution API specification even defines a “pruned history unavailable” error for affected calls. So “does not require historical state” is not the same as “will work forever on every full node.”
Do you need an archive node for eth_getLogs?
Not necessarily. eth_getLogs searches logs recorded in transaction receipts; it does not ask for an account or contract’s state at the end of each block. A node with the required receipt and log history can answer an old log query even if old world state has been pruned. The official `eth_getLogs` specification defines filters by block range or block hash and separately accounts for pruned history.
In practice, providers often route long-range logs to infrastructure they label “archive,” because those nodes retain broad history and are sized for historical workloads. That routing choice does not change the underlying distinction. Before a backfill, test:
- the earliest required block;
- dense and sparse contracts;
- the provider’s block-range and response-size limits;
- timeout and 429 behavior under realistic concurrency;
- the same request after failover.
Do not request a more expensive or operationally heavier node solely because an indexer uses logs. Request guaranteed log retention and measured backfill capacity. Add historical state only if the indexer also executes old eth_call requests, reads old storage, produces proofs, or needs state-dependent traces.
Does an archive node guarantee debug or trace methods?
No. Archive retention and tracing are separate decisions. A node can retain every historical state while exposing only the standard eth_* namespace. It can also expose debug_* but not Parity-style trace_*, or support only particular tracers and timeouts.
Geth’s `debug_traceTransaction` documentation describes transaction replay, tracer selection, timeout, and a reexec limit for reconstructing missing historical state. Other EVM clients expose different namespaces and tracer behavior. Rollups can add further client-specific constraints.
For each chain, record the exact calls you need—such as debug_traceTransaction with callTracer, debug_traceCall, trace_transaction, or trace_block—and test representative recent and old transactions. Verify response shape as well as HTTP success. A fallback that keeps eth_blockNumber alive but lacks the required tracer is not a capable trace fallback.
How do you turn a product requirement into a node requirement?
Start with the user-visible output and work backward:
- List every RPC method. Capture chain, parameters, block depth, tracer configuration, response size, and expected rate.
- Separate live sync from backfill. Current reads, recent reorg handling, and a one-time genesis backfill have different capacity needs.
- Name the retained data. Decide whether each call needs state, blocks, transaction indexes, receipts/logs, trie proofs, or replay inputs.
- Set the oldest required block. “Historical” is too vague. A 30-day accounting window and genesis-to-head analytics imply different retention.
- Define correctness after failover. The secondary must preserve the method, depth, and tracer—not only return HTTP 200.
- Measure the workload. Run representative ranges and concurrency long enough to observe timeouts, throttling, and slow cold reads.
This process may produce a mixed design: a pruned full node for head traffic, an archive path for historical state, a log-optimized backfill path, and method-aware routing for traces. One node type does not have to serve every workload.
How can you test whether an RPC endpoint really has archive state?
Use a known canonical block that is far older than the endpoint’s advertised recent-state window and an address relevant to your application. Test at least two state methods rather than relying on eth_blockNumber or an old block lookup.
A minimal Ethereum state probe is:
curl -s -X POST 'https://YOUR_RPC_URL' -H 'Content-Type: application/json' -d '{"jsonrpc":"2.0","method":"eth_getBalance","params":["0x0000000000000000000000000000000000000000","0xF4240"],"id":1}'
Block 0xF4240 is block 1,000,000. A valid quantity result shows that this call was served; a block object from the same height would not prove historical state availability. Repeat with a known contract using eth_getCode, eth_getStorageAt, or eth_call, and test the actual oldest block your product needs.
For multi-call workflows, prefer a block hash where the client supports EIP-1898. Its `requireCanonical` option lets the endpoint distinguish a missing block from a block that is no longer canonical. Record the block number and hash used by the test so a reorganization cannot make two successful calls describe different states.
Finally, run the same probes through the production router while deliberately removing the preferred upstream. Archive access that disappears during failover is not an end-to-end guarantee.
What should you ask an RPC provider before relying on archive access?
Ask questions that can be answered with a method, block, and test result:
- Which chains retain historical state, and what is the earliest queryable block?
- Are block, transaction, receipt, and log histories retained to the same depth?
- Does historical
eth_getProofwork, or only historical flat-state reads? - Which
debug_*andtrace_*methods and tracers are enabled per chain? - Are archive methods available on the same plan and endpoint?
- What range, response-size, timeout, rate, and concurrency limits apply?
- Does fallback preserve the same history and method capability?
- How are pruned-history errors represented?
- Can the provider supply a test period using your real workload?
Avoid a yes-or-no archive checkbox. A precise capability matrix is more useful than a node label, especially across EVM chains whose clients and data-retention models differ.
When should you self-host the archive node?
Self-hosting makes sense when historical data is strategic, traffic is large and predictable, custom client settings or proofs are required, and the team is prepared to own storage, sync, upgrades, monitoring, corruption recovery, and capacity. It can also reduce dependence on a provider for irreplaceable research or compliance data.
A managed archive RPC is usually the better starting point when the requirement is method access rather than control of the database. It avoids a long sync or snapshot workflow and shifts day-two operations away from the application team. The trade-off is that you must verify retention, limits, fallback, and change management instead of controlling them directly.
If you are comparing the operating models, include engineering and incident work as well as servers and disks. The related self-hosted nodes versus RPC provider cost guide covers that calculation; the archive decision here should supply its required node shape and workload inputs.
What archive RPC capability does SolidRPC publish?
SolidRPC provides one authenticated HTTPS endpoint format per supported chain: https://rpc.solidrpc.io/YOUR_API_KEY/evm/<chainId>. The live network catalog is the source of truth for each chain's full or archive service class and its standard, debug_*, or trace_* method families. Supported archive calls use the same endpoint and cost one response unit without a separate archive surcharge; see the archive-node documentation and pricing.
This is an outcome-level service boundary: customers integrate once and SolidRPC manages the RPC service. It is not a promise of single-tenant infrastructure, and it does not make every historical method interchangeable. Historical state, proofs, logs, and traces remain separate requirements. Probe the exact chain, method, block, response shape, and failure behavior before migrating a production workload.
Archive RPC decision checklist
- Inventory methods by chain, block depth, rate, and response size.
- Mark state queries separately from blocks, transactions, receipts, and logs.
- Treat historical proofs as a trie-retention requirement, not just archive state.
- Treat
debug_*andtrace_*as client capabilities, not archive synonyms. - Define the oldest block that must work in normal sync and backfills.
- Test known old state with at least two representative methods.
- Test old logs, receipts, proofs, and traces independently when required.
- Pin related reads to a block hash where supported.
- Verify range, timeout, rate, concurrency, and response-size limits.
- Verify that every required capability remains available during a documented failover test.
- Decide whether the workload needs self-hosted control, managed access, or a mixed route.
- Re-run the matrix after client upgrades, pruning changes, or provider migrations.
The durable conclusion is simple: buy or operate the data and methods your application can prove it needs. “Archive node” is a useful starting label, not a complete production specification.
Frequently asked questions
- What is an EVM archive node?
An EVM archive node retains historical state so methods such as
eth_getBalance,eth_getCode,eth_getStorageAt, andeth_callcan describe an old block. Block, receipt, log, proof, and trace retention are separate capabilities that still need method-level testing.- What is the difference between a full node and an archive node?
A full node validates the chain and usually retains current plus some recent state, while an archive node retains historical state across a much deeper range. The exact window and retained block, receipt, log, proof, and trace data depend on the chain and configuration.
- Do you need an archive node for eth_getLogs?
Not automatically.
eth_getLogsreads receipt and log history rather than historical world state. You need an endpoint that retains the required logs and can serve the range, while archive state is necessary only if the workflow also queries old balances, storage, code, or contract calls.