Skip to content

Optimize Your Full Node

Optimizing your full node helps keep it online, up to date, and operating quickly. Faster nodes have an advantage over slower nodes because they tend to receive new data first and they minimize the time between placing and resolving orders. Optimize your full node by connecting to trusted nodes, taking precautions against falling out of sync with the network, and configuring storage settings.

Prerequisites

You need a running, non-validating full node that is connected to a network.

If you created a system service for your node by following the instructions on the previous page, Set Up a Full Node, start it with:

systemctl start ritbitd

To start the node directly instead, you must include the flag --non-validating-full-node=true. The flag disables the functionality intended for validator nodes and enables additional logic for reading data. Your CLI may prompt you to configure additional variables in your environment or include them in your command.

With Cosmovisor:

cosmovisor run start --non-validating-full-node=true

With the ritbitd binary:

ritbitd start --non-validating-full-node=true

Save a List of Trusted Nodes

Specify a list of healthy, stable nodes that you trust. Your node prioritizes connecting to those nodes, speeding up the process of connecting or re-connecting to the network. Connecting directly with a peer node is faster than connecting to a seed node and then finding new peers.

Save a List of Persistent Peers

You can save a list of healthy, stable nodes in the persistent_peers field of your config.toml file.

Start from the public full node listed on the Resources page, then discover additional peers from a running node:

curl -s https://rpc.mainnet.rubin.trade/net_info \
  | jq -r '.result.peers[] | "\(.node_info.id)@\(.remote_ip):26656"'

Add a comma-separated list of peer addresses to the persistent_peers field in your config.toml, like in the following example:

# config.toml
# Example for ritbit-mainnet
persistent_peers="f907537d0ea47759e369f7bac5cb2c22be5e3c93@213.165.223.41:26656"

Prepare to Restore Your Node

To minimize downtime in case your node falls out of sync, make preparations to restore your node quickly.

Your full node can fall out of sync with the rest of the network for a variety of reasons, including a bad software upgrade, unexpected node crashes, or human operational error. To re-sync with the network, your full node needs to replay the history of the network, which can take a long time.

You can avoid replaying the whole history in one of two ways. A snapshot is a compressed archive of a node's data directory that you download over HTTP and unpack in place. State sync fetches the application state from your peers over the P2P network instead, with no archive to download. Snapshots are the simpler option and are always available; state sync is faster and needs no disk space for an intermediate archive.

Save a Snapshot on Your System

Keep a recent snapshot on your node's system so you can restore quickly if it falls out of sync.

Snapshots are published to a public bucket and refreshed regularly — see Snapshots for the current listing and a one-liner that fetches the newest one. Set Up a Full Node covers how to restore one.

Configure Your Node's State Sync Setting

State sync is a CometBFT feature that fetches a recent application state from your peers over P2P, verifies it against a block hash that you supply, and starts the node from that height. Unlike a snapshot, nothing is transferred out of band: there is no archive to locate, download, or unpack, and no temporary disk space is needed for it.

State sync only works if at least one reachable peer serves state sync snapshots. The public full nodes listed on the Resources page serve them, so you can state sync against the network without arranging anything in advance.

Sync a New Node with State Sync

First derive a trusted height and block hash from a public node. Any recent height inside the trusting period works — the light client verifies forward from it to whatever snapshot height the peers offer, so the trusted height does not need to match the snapshot:

RPC=https://rpc.mainnet.rubin.trade
HEIGHT=$(( $(curl -s $RPC/status | jq -r '.result.sync_info.latest_block_height') - 4000 ))
curl -s "$RPC/block?height=$HEIGHT" \
  | jq -r '"trust_height = \(.result.block.header.height)\ntrust_hash = \"\(.result.block_id.hash)\""'

Then put those values into the [statesync] section of your config.toml:

# config.toml
[statesync]
enable = true
 
# CometBFT requires at least two entries. It cross-checks the header they return,
# so prefer two independent nodes — for example the public endpoint plus a node
# you operate. Listing the same endpoint twice works, but then a single host
# fully determines what state your node trusts.
rpc_servers = "https://rpc.mainnet.rubin.trade:443,https://rpc.mainnet.rubin.trade:443"
 
# From the command above.
trust_height = 12960000
trust_hash = "0000000000000000000000000000000000000000000000000000000000000000"
 
# The light client's trusting period. It must be shorter than the network's
# unbonding period, which is 30 days on both ritbit-mainnet and ritbit-testnet.
trust_period = "168h0m0s"

Start the node with an empty data directory. It discovers a snapshot from its peers, downloads the chunks, verifies them against trust_hash, and then continues with normal block sync from the snapshot height.

Serve State Sync Snapshots

If you want your own node to serve state sync to others — or to your own future nodes — enable snapshot creation in app.toml:

# app.toml
[state-sync]
 
# Take a snapshot every 2000 blocks. 0 disables snapshot creation, which is the default.
snapshot-interval = 2000
 
# Keep the 2 most recent snapshots and serve them.
snapshot-keep-recent = 2

Two things to account for before enabling it:

  • Retention. A snapshot can only be taken at a height whose state is still on disk, so pruning-keep-recent must comfortably exceed snapshot-interval × snapshot-keep-recent. With the values above, keep at least 4000 recent heights.
  • Disk. Snapshots are stored under data/snapshots. A snapshot holds only the current application state, not the retained history, so it is far smaller than application.db — on ritbit-testnet a snapshot is under 1 MB while application.db is several GB. Creation is a short burst of I/O every snapshot-interval blocks, which is the reason to serve snapshots from a public full node rather than a validator.

Configure a Pruning Strategy

Pruning discards old application state to keep storage requirements down. Configure it in your app.toml:

# app.toml
pruning = "custom"
 
# Number of recent heights to retain.
pruning-keep-recent = "5000"
 
# How often the pruning routine runs, in blocks.
pruning-interval = "100"

pruning = "everything" keeps only the last two states and gives the smallest footprint, but a node configured that way cannot answer queries about past heights, cannot produce ICS-23 proofs for anything but the current block, and cannot serve state sync snapshots. Use it only where none of that matters.

If you want to query historical data, raise pruning-keep-recent accordingly. Retaining more states increases storage requirements.