Skip to main content
A frozen node is a full node that stops one block before an upgrade height. It runs the release that was live before the upgrade and keeps answering read queries for the heights below it. If you serve historical RPC queries, for example as an RPC provider or a block explorer, run one frozen node for each upgrade.

How freeze mode works

An upgrade can remove modules and stores that earlier heights depend on. After the upgrade, queries for those heights can fail on the new release or give different results. A node that still runs the outgoing release answers them the way the chain did at the time. Freeze mode runs such a node. You set freeze-height to the upgrade height. The node executes every block below that height and stops before the upgrade block. It does not halt or exit at the boundary. It keeps serving queries from the state at freeze-height - 1, which is also its latest block. From startup, freeze mode changes the node like this:
  • Query endpoints stay up: the Tendermint RPC, the REST API, gRPC, and the EVM JSON-RPC.
  • Transaction and evidence submission fail with RPC writes are disabled in freeze mode. This includes eth_sendRawTransaction.
  • Mempool gossip is off.
  • State sync is off. If it is enabled in config.toml, the node logs a notice and uses block sync.
  • Block sync and consensus stop before freeze-height and do not advance.
Each frozen node covers the heights up to its own upgrade. To serve the full history of a network, run one frozen node for each upgrade, and a live node on the current release for the heights after the last upgrade. Freeze mode first shipped in v6.6.3. The oldest frozen node therefore runs v6.6 and serves every height below the v6.7 upgrade height that its data holds.

Freeze heights

Set freeze-height to the upgrade height. Run the latest patch of the release that the upgrade replaced. Your live node serves the heights from the freeze height on.
Use v6.6.4 or a later v6.6 patch. On v6.6.3, the EVM RPC servers do not start again after the process restarts, because a frozen node executes no block that would start them.
To read upgrade heights from the chain, query the upgrade module. The first command returns the height at which v6.7 was applied on Sei Mainnet. For Sei Testnet, use https://rest-testnet.sei-apis.com. The second command returns the name and height of the next scheduled upgrade, or no upgrade scheduled.

Before you begin

You need:
  • A full node. Freeze mode does not run in validator or seed mode.
  • A copy of a node’s data directory that is below the freeze height. The node refuses to start if its application, block store, or state store has reached freeze-height.
  • The history that you want to serve. A frozen node serves only what its data directory holds. To serve the full history, copy an archive node.
  • Disk space for a full copy of that data. The copy stops growing when it reaches the freeze height.
  • Peers that store the blocks from the copy’s height up to the freeze height. The node fetches these blocks with block sync before it freezes. Pruned nodes delete old blocks, so for a copy far below the freeze height, list archive nodes in persistent-peers in config.toml.
Take the copy before the chain reaches the upgrade height. A node saves each block before it executes it, so a node that halted at the upgrade height already holds the upgrade block. With that block in its block store, the node refuses to start with that freeze-height. After the chain has passed the upgrade height, you can build a frozen node only from data below that height, such as a backup.
Both networks are past the v6.7 freeze height. To build a v6.7 frozen node now, start from a backup of an archive node taken below the freeze height, or from a provider’s full-history archive snapshot taken below it. Providers refresh their snapshots regularly, so their current snapshots are usually above the freeze height. Check the height of a snapshot before you download it. The first step below explains how to start from a snapshot.

Set up a frozen node

These steps use the Sei Mainnet values for the v6.7 upgrade. For Sei Testnet, use the values in Freeze heights.
1

Copy the data directory

Stop seid on a node that holds the history you want to serve. Take a volume snapshot of its data disk, or copy its whole home directory, including data/ and wasm/, to the new host. Then start the source node again.
The --exclude flag keeps the validator signing key on the source host. A frozen node never signs blocks, so it does not need that key. The remote path .sei/ is relative to the home directory of <user>, so connect as the user that runs seid on the new host.On the new host, delete the node key. If you took a volume snapshot, also delete the validator key. seid generates new keys when it starts. Two nodes must not share a node key.
To start from a provider’s archive snapshot instead, take these steps on the new host:
  1. Install the outgoing release, as described in the next step.
  2. Run seid init <moniker> --chain-id pacific-1 --mode archive. It writes the genesis file and a configuration that keeps all history.
  3. In config.toml, set persistent-peers to archive nodes that store the blocks from the snapshot height up to the freeze height. Each entry has the form <node-id>@<host>:26656, and seid tendermint show-node-id prints the node ID on an archive node that you run.
  4. Restore the snapshot with the snapshot guide, but stop before its restart step.
Then continue with step 3.
Do not start seid on the new host before you set the freeze height in step 3. If the copy runs without freeze-height and reaches the upgrade height, it stores the upgrade block and can never freeze at that height.
If you run more than one archive node, you can freeze one of them in place instead. Set freeze-height on it and restart it before the chain reaches the upgrade height. It keeps its node key.
2

Install the outgoing release

Install v6.6.4 on the new host. Do not start seid yet.
The v6.6.4 release has a prebuilt binary for Linux x86_64 only.
Check the version:
Keep this binary on the frozen node. Exclude the node from any process that upgrades the binaries of your other nodes.
3

Set the freeze height

In $HOME/.sei/config/config.toml, make sure that the node runs in full mode. mode is a top-level key:
In $HOME/.sei/config/app.toml, set freeze-height to the upgrade height, and set halt-height and halt-time to 0. The three keys sit together in the base configuration at the top of the file, before the first [section] header:
app.toml
An app.toml from a release before v6.6.3 has no freeze-height line. In that case, add the line after halt-height.If you copied an archive node, keep its pruning settings, so that the node keeps every version up to the freeze height. Do not start the node with --grpc-only. The node refuses to start when freeze-height is combined with --grpc-only, halt-height, or halt-time. It also refuses to start with Autobahn enabled, that is, with a non-empty autobahn-config-file in config.toml.
4

Start the node

A new host has no seid service yet. Create one that runs the v6.6.4 binary directly. Do not run a frozen node through Cosmovisor, which exists to switch binaries at upgrade heights. Run these commands as the user that runs seid:
$(which seid) writes the full path of the binary that you checked in step 2 into ExecStart. If the host already has a seid service, run systemctl cat seid and check that its ExecStart runs that binary.Start seid and follow the log:
The log shows Freeze mode enabled at startup. The node then syncs to height 236449999. When it reaches that height, it logs Block sync stopped before configured freeze height or Consensus frozen before configured height, and it keeps serving queries.If the node exits with <source> height <n> has already reached freeze height <h>, its data is at or above the freeze height. Start again from a copy that is below it.
5

Verify the frozen node

Check that the Tendermint RPC and the EVM RPC both report a latest block one below the freeze height:
Restart the node once, and run the EVM check again. This confirms that the EVM RPC comes back after a restart.If you scrape the node’s Prometheus metrics, sei_chain_app_build_info shows the running release in its seid_version and commit labels. Alert when either label changes.
6

Back up the frozen node

After the node reaches the freeze height boundary, back up its data directory, for example with a volume snapshot. The node executes no more blocks, so the backup stays valid. Keep it, because after the chain has passed the freeze height, you can rebuild this node only from data below that height.

Route queries by block height

Clients usually connect to one endpoint. The frozen-rpc-router binary gives them one for EVM JSON-RPC over HTTP. It reads the block height in each request and sends the request to the matching frozen node or to the live node. The router is a separate binary in the sei-chain repository, and make install does not install it. Build it from v6.6.3 or a later release tag:
Pass the live node with --live-node, and pass each frozen node with a --frozen-node <freeze-height>=<address> flag. In this Sei Mainnet example, the router runs on the live node’s host. Move the live node’s EVM HTTP port to 9545 with http_port under [evm] in app.toml, so that the router can listen on 8545. The frozen node runs on its own host.
Each freeze height is an exclusive boundary. The router sends heights up to 236449999 to the frozen node, and it sends 236450000 and later to the live node. When you add a frozen node for a later upgrade, add one more --frozen-node flag. Each frozen node then serves the heights from the previous freeze height up to its own. The Sei-RPC-Route response header shows which backend answered:
A request for latest returns live. A batch that the router splits across backends returns mixed. Plan around these limits:
  • The router handles only EVM JSON-RPC over HTTP. For the Tendermint RPC, the REST API, or gRPC at old heights, query the frozen node directly.
  • Requests without a block number go to the live node. This includes lookups by block or transaction hash, such as eth_getTransactionReceipt.
  • WebSocket clients must connect to the live node directly.
  • An eth_getLogs or eth_feeHistory range must stay within one interval. A range that crosses a freeze height fails with JSON-RPC error -32000.
  • The router has no authentication. Bind it to 127.0.0.1, or put it behind a firewall or reverse proxy.
For every flag and routing rule, see Frozen RPC router in the technical reference.

Prepare for each upgrade

Each upgrade adds one frozen node:
  1. When an upgrade proposal passes, read its height with seid query upgrade plan.
  2. Before the chain reaches that height, set up a frozen node on the latest patch of the current release, with freeze-height set to the upgrade height.
  3. After the new frozen node reaches its boundary, back it up and add it to the router with one more --frozen-node flag.
Never upgrade a frozen node to the release that its freeze height introduces, and never change its freeze-height. You can install a later patch of the same release line, for example v6.6.4 over v6.6.3. Keep each frozen node for as long as you serve queries for its heights.