An archive node keeps the state of every block from genesis. A full node keeps a recent window only. This post says which reads need an archive node, how xOne stores the history, and where each client stands today.

What an archive node does

A full node answers state reads inside its state window. Below the window it refuses the read with a typed unsupported history error. An archive node answers at any canonical block.

These reads need the historical state (xOneRS archive guide):

  • eth_getBalance
  • eth_getTransactionCount
  • eth_getCode
  • eth_getStorageAt
  • eth_call

Explorers, indexers and audit tools use these reads on old blocks.

How xOne stores the history

The four clients use the same core design. Each block also writes two history tables:

  • AccountHistory: the hashed address, then the block number. The value is the account record before the block.
  • StorageHistory: the hashed address, the hashed slot, then the block number. The value is the slot word before the block.

To read key k at block n, the node seeks the first history row of k above n. That row holds the value after n. If no such row exists, k has not changed since n, and the head state holds the value. One cursor seek answers one key. An unwind deletes the history rows of the blocks it removes.

In xOneRS the history rows are written in the same MDBX transaction as the block. The per-block changesets that unwind uses keep their window. Only the history rows are never pruned (changesets spec).

Start an archive node

In xOneRS, start on an empty datadir with full sync:

xone --network net2040 --datadir <empty dir> --gcmode archive --syncmode full ...

The same rules apply in the four clients:

  • --gcmode archive needs an empty datadir. The datadir keeps its mode afterwards.
  • A datadir written in the other mode refuses to start. In xOneRS the error names the stored mode.
  • --gcmode archive with --syncmode snap or --minimal is refused. xOneRS, xOneTS and xOnePy also refuse fast. A snapshot has no history below its anchor.
  • The ethstats board shows gcMode: archive.

The flag is documented in the flag reference. It follows the geth-XDC flag name.

Status per client

Status is from main and from the net2040 tracker comment of 2026-11-14T18:30Z (xOneRS#140). The xOneTS, xOnePy and xOneC repositories are private.

REFERENCE TABLEScroll to explore all columns →
Client Archive code on main Archive node on net2040
xOneRS Merged in PR #416 on 2026-11-14. #152 is closed. Full sync from genesis to block 832,598 on 2026-11-14. 378 of 378 reads equal to the geth-XDC archive (PR #416).
xOneTS Merged in PR #89 on 2026-11-13. #74 is closed. 130 of 130 reads equal at blocks 0, 1, 16, 16,000 and 18,000. The tracker lists the node as syncing from genesis, at block 184,398 of tip 840,762.
xOnePy Merged in PR #95 on 2026-11-14. #85 is still open. At the tip. 124 of 124 historical reads equal. Three of three seals on a borrowed seat.
xOneC Merged in PR #80 on 2026-11-13. #61 is closed. At the tip. 245 of 245 historical reads equal. Three of three seals on a borrowed seat.

xOneTS has no archive node at the tip yet. Its sync-modes document lists the lag sample at the tip and the reads at later blocks as open (sync modes).

The 825,238 figure

The tracker row for the first Rust archive node says: state is retained from block 825,238 only, with no true state archive. PR #416 gives the same symptom before the change: eth_getBalance at block 16 answered unsupported history, with first retained block 825,238. The merged archive mode removes that limit. The tracker row has not been updated.

Growth

xOneRS measured the cost on net2040 (full sync to block 832,598, 2026-11-14):

REFERENCE TABLEScroll to explore all columns →
chain.mdbx whole datadir
Archive 5.03 GB 22.8 GB
Full node, same chain 2.9 GB 20.6 GB

On net2040 the history costs about 2.1 GB, almost all of it from the dense range (blocks 0 to 215,000, with blocks of more than 20,000 transactions). The range from 215,000 to 793,000 is mostly empty blocks and adds about 81 MB of chain.mdbx per 100,000 blocks (archive guide).

Retention and the open gaps

spec/retention.md covers the other side: a node that starts from a snapshot at pivot P. It lists each rule that reads below a block and the longest lookback. The window is derived from the chain spec, not set as a constant. For Apothem at pivot 84,000,000 the header window is 4,500 blocks. The state window is the pivot itself.

An archive node needs no such window for state, because it holds every block. For that reason it syncs from genesis and cannot start from a snapshot.

These reads are not served from the history yet in xOneRS: eth_getProof below the window, snap/1 at old roots, and the tracers. In xOneTS and xOneC, snap/1 serves the roots of the last 4,096 blocks only, and historical eth_getProof is not served. In xOnePy, snap/1 serves any canonical root while the rebuilt state is at most 4,194,304 rows.

Sources