Logo
New RPC users get 35% off their first monthView the offer
OnFinality Learn
Infrastructure & Operations14 min read

Sui Snapshots: Formal vs RocksDB and Full Node Restore

How Sui database snapshots work at epoch boundaries, when to use formal versus RocksDB snapshots, and how to restore a full node safely.

TL;DR

A Sui database snapshot is a point-in-time view of a node's store taken at the end of an epoch, so every artifact is addressed by epoch rather than by arbitrary block height. RocksDB snapshots preserve the full database store including indices and non-pruned data, which makes them larger but suitable for RPC nodes that serve historical lookups. Formal snapshots are database-agnostic, contain only the end-of-epoch live object set, are smaller and faster to restore, and are cryptographically verifiable against a committee-signed epoch commitment, but they contain no indexes and are therefore not suitable for historical RPC. Restoring a full node means either placing a RocksDB epoch directory at <db_path>/live or running sui-tool download-formal-snapshot with the correct genesis, network, and bucket flags, then confirming the node catches up to the expected epoch and checkpoint height before routing traffic.

The Epoch-Partitioned Snapshot Mental Model

A Sui database snapshot is a point-in-time view of a node's store captured at the end of an epoch. Sui is epoch-partitioned: epochs are the protocol's unit of validator-set change and reconfiguration, so every snapshot artifact is addressed by epoch, never by an arbitrary block height. This is the single most important difference from EVM-style snapshot and restore tooling, where operators routinely reason in block numbers and rewind to a height. On Sui, the question is always which epoch you are restoring to, and whether the artifact you hold is the one the committee committed to for that epoch.

The Sui Database Snapshots documentation is the authoritative source for the two artifact types and their restore procedures. The full node documentation covers node configuration, monitoring, and updating, which is where snapshot production settings live. The data management documentation explains pruning and archival stores, and states why formal snapshots are not suitable for historical RPC nodes. Read those three pages alongside this article; the platform behavior described here is documented there, while the operational recommendations are ours.

Because snapshots are epoch-addressed, a restore is also a chain-identity check. You must know which network you are restoring (mainnet, testnet, or another), which genesis blob that network uses, and which epoch you intend to land on. A snapshot from the wrong network or a stale epoch will either fail verification or leave the node far behind the current epoch, and neither outcome is obvious from the file listing alone.

  • Snapshot unit: end-of-epoch view, addressed by epoch number.
  • Chain identity: network plus genesis blob must match the snapshot.
  • Restore goal: reach the snapshot epoch, then catch up to the live network head.

Formal Versus RocksDB Snapshots and Their Trade-Off

A RocksDB snapshot is a point-in-time view of the database store, including non-pruned data, additional indices, and other data the node maintains. It is a larger artifact, but it preserves the indices an RPC node needs to answer historical and indexed queries. A formal snapshot is database-agnostic: it contains only the end-of-epoch live object set, meaning the set of all object versions eligible as input objects for future transactions. It has a much smaller storage footprint and restores faster, and it is natively supported by the Sui protocol and cryptographically verifiable against a committee-signed commitment at the epoch being restored.

The restriction that matters most in production is documented plainly: formal snapshots are not suitable for an RPC node that does historical data lookups, because they contain no indexes. The choice between the two types is therefore decided by the job, not by artifact size. Validators and state-sync full nodes can start from a formal snapshot. A node that must serve historical reads and indexed queries must not; it needs the RocksDB artifact or a full sync that rebuilds the indices itself.

This is the same operational split described in Sui archive nodes and historical RPC: archive and historical-serving roles depend on retained data and indexes, while a state-sync participant only needs the live object set to validate forward. If you are still deciding which interface your node should expose, the Sui full node RPC endpoint setup guide covers binding and configuration, and the Sui gRPC guide covers the newer query interface.

  • RocksDB snapshot: full store view, includes indices and non-pruned data, larger, needed for historical RPC.
  • Formal snapshot: live object set only, database-agnostic, smaller and faster, verifiable against the epoch commitment, no indexes.
  • Decision rule: choose by the queries the node must answer, not by download size.

Restoring a Full Node from a RocksDB Snapshot

The RocksDB restore path is deliberately simple: you are placing a directory where the node expects its live store. Pull the epoch directory from the managed snapshot bucket with cloud object-store tooling into a temporary directory, then place it at <db_path>/live, fix ownership so the sui-node process can read and write it, and start sui-node. The managed Mysten Labs DB snapshot buckets are Requester Pays, meaning the operator pays egress, so a reader who needs a RocksDB snapshot must budget for that transfer.

Two details cause most failures. First, the directory layout: the node expects the epoch's contents under <db_path>/live, not a nested copy of the bucket path, so verify the structure before starting the node. Second, ownership and permissions: a store copied as root and then read by an unprivileged service account will fail at startup in ways that look like corruption. Fix ownership before the first start, and keep the temporary download directory on a volume with enough free space for both the archive and the extracted store.

Because the RocksDB artifact is a store view rather than a protocol-verifiable object, your integrity check is structural and operational: confirm the epoch directory is complete, confirm the node starts without store errors, and confirm it advances past the snapshot epoch. The cryptographic verification story belongs to formal snapshots, described next.

  • Download the epoch directory to a temporary path with your cloud object-store CLI.
  • Place contents at <db_path>/live and correct ownership before first start.
  • Budget for Requester Pays egress on managed DB snapshot buckets.
  • Verify by clean startup and forward progress past the snapshot epoch.

Restoring a Full Node from a Formal Snapshot with sui-tool

Formal snapshots are restored with sui-tool download-formal-snapshot. Use --latest or an explicit --epoch, point --genesis at the network's genesis.blob, set --network, and set --path to the target database directory. For the free permissionless buckets, use --no-sign-request; for an explicit bucket, pass --snapshot-bucket and --snapshot-bucket-type along with the documented cloud environment variables for credentials. Keep checkpoint and transaction pruning configuration in view so the node starts with the retention you intend rather than a default.

The formal restore performs verification by default against the epoch commitment and rolls the node back if verification fails. That behavior is the reason formal snapshots are the safer onboarding path for state-sync participants: the tool checks the artifact against the committee-signed commitment for the epoch being restored, so a corrupted or wrong-epoch download does not silently become your node's state. After the tool completes, start sui-node and watch it catch up.

# Restore the latest formal snapshot for mainnet into a target db path.
# Run from the sui-tool binary matching your sui-node release.
sui-tool download-formal-snapshot \
  --latest \
  --genesis /opt/sui/config/genesis.blob \
  --network mainnet \
  --path /opt/sui/db \
  --no-sign-request

# Pin a specific epoch instead of --latest:
#   --epoch 742
#
# Use an explicit bucket instead of the free permissionless bucket:
#   --snapshot-bucket <bucket-name> \
#   --snapshot-bucket-type <gcs|s3> \
#   (plus the documented cloud credential environment variables)
#
# Then start the node with your intended pruning configuration:
#   sui-node --config-path /opt/sui/config/fullnode.yaml

The Cost and Access Model for Snapshot Buckets

The Mysten Labs managed DB snapshot buckets are Requester Pays: the operator downloading pays egress. Free permissionless buckets exist for formal snapshots only and are served over Cloudflare R2, which is why the --no-sign-request flag appears in formal restore examples. The asymmetry is the practical consequence of the artifact types: formal snapshots are small enough and protocol-verifiable enough to be offered permissionlessly, while RocksDB snapshots are large store views whose transfer cost is borne by the requester.

For planning, treat this as a budgeting question rather than a technical one. A reader who needs a RocksDB snapshot must budget for egress from the managed bucket. A reader who only needs to join as a state-sync full node or validator can use the free formal path. If you are choosing a managed provider instead of running your own node, the Sui networks page lists the network options, and RPC pricing and the API service describe the hosted alternatives to self-hosting.

  • Managed DB snapshot buckets: Requester Pays, operator pays egress.
  • Free permissionless buckets: formal snapshots only, served over Cloudflare R2.
  • Formal restore examples use --no-sign-request against the free bucket.

Producing Snapshots from Your Own Full Node

Full nodes do not take snapshots by default. To produce them, enable either db-checkpoint-config with perform-db-checkpoints-at-epoch-end plus an object-store-config block, or state-snapshot-write-config with object-store-config plus object-store-connection-limit, in fullnode.yaml, then restart the node. The first produces the RocksDB-style database checkpoint; the second writes formal state snapshots. Treat the bucket credentials in these blocks as write-scoped secrets and scope them to the snapshot prefix only.

Sui explicitly encourages the community to host additional snapshots for data availability, so producing them is a legitimate contribution, not just an internal convenience. The operational discipline is the same as consuming them: know which epoch you wrote, keep the artifact addressable by epoch, and publish what you have. The Sui checkpoint streaming and the ledger service article covers the adjacent checkpoint-stream mechanism if you are building data-availability infrastructure around snapshots.

  • db-checkpoint-config: perform-db-checkpoints-at-epoch-end plus object-store-config.
  • state-snapshot-write-config: object-store-config plus object-store-connection-limit.
  • Restart after editing fullnode.yaml; use write-scoped bucket credentials.
  • Record the epoch written and publish the bucket name and retention.

Verifying a Restore Against the Expected Chain and Head

An honest restore check has two parts. First, confirm the formal snapshot verification ran: the tool verifies against the epoch commitment by default and rolls back on failure, so a completed restore without a rollback is evidence the commitment check passed. Second, confirm the restarted node is on the expected chain and that its checkpoint head is advancing. Do not route traffic until both are true.

The script below queries a node's JSON-RPC endpoint for the chain identifier and the latest checkpoint sequence number, samples twice, and reports whether the head advanced. It uses only standard JSON-RPC methods and Node's built-in fetch, so it runs anywhere Node 18 or later is installed. Point it at your own node's endpoint, not a public one, when validating a restore.

// verify-restore.mjs — confirm chain identity and advancing checkpoint head.
// Usage: node verify-restore.mjs http://127.0.0.1:9000 <expected-chain-id>
const endpoint = process.argv[2] || "http://127.0.0.1:9000";
const expectedChainId = process.argv[3];

async function rpc(method, params = []) {
  const res = await fetch(endpoint, {
    method: "POST",
    headers: { "content-type": "application/json" },
    body: JSON.stringify({ jsonrpc: "2.0", id: 1, method, params }),
  });
  const body = await res.json();
  if (body.error) throw new Error(`${method}: ${body.error.message}`);
  return body.result;
}

const chain = await rpc("sui_getChainIdentifier");
console.log("chain identifier:", chain);
if (expectedChainId && chain !== expectedChainId) {
  console.error(`MISMATCH: expected ${expectedChainId}`);
  process.exit(1);
}

const first = await rpc("sui_getLatestCheckpointSequenceNumber");
console.log("checkpoint head (sample 1):", first);
await new Promise((r) => setTimeout(r, 15000));
const second = await rpc("sui_getLatestCheckpointSequenceNumber");
console.log("checkpoint head (sample 2):", second);

if (BigInt(second) > BigInt(first)) {
  console.log("OK: checkpoint head is advancing");
} else {
  console.error("WARN: head did not advance in the sample window");
  process.exit(2);
}

A Results Table for Your Own Measurements

Snapshot size, download time, and restore duration are environment-specific and must not be asserted as fixed facts. Measure them on your own infrastructure and record the results. The table below is a template to fill in per artifact and per run; keep the epoch, artifact type, and network in every row so comparisons stay honest.

Run each measurement at least twice, on the same host class and network path, and note whether the source was the free formal bucket or a Requester Pays managed bucket. If you publish the numbers, publish the method alongside them.

  • Columns: date, network, epoch, artifact type, source bucket, artifact size, download duration, restore duration, verification result, final checkpoint head.
  • Record host class, region, and egress path so the numbers are reproducible.
  • Treat any single run as anecdotal until repeated.

Limitations, Trade-Offs, and Failure Modes

The central limitation is the index gap: a formal snapshot restores a node that can validate forward but cannot answer historical indexed queries, because it contains no indexes. If your service contract includes historical reads, the formal path is the wrong tool regardless of how much faster it is. The RocksDB path preserves indices but costs more storage and egress, and it is not cryptographically verifiable in the same way, so your integrity check is structural.

Epoch addressing is a second limitation. A snapshot is only valid for the epoch it was taken at, and a stale artifact leaves the node far behind. There is no rewind-to-height convenience. Third, the access model is asymmetric: free formal buckets versus Requester Pays DB buckets means the cheaper path is also the more restricted one. Finally, producing snapshots requires configuration changes and a restart, and misconfigured bucket credentials are a common cause of silent non-production.

  • Formal snapshots cannot serve historical indexed queries.
  • RocksDB snapshots cost more storage and egress and lack protocol-level verification.
  • Snapshots are epoch-bound; stale artifacts mean long catch-up.
  • Free buckets cover formal snapshots only.
  • Snapshot production is opt-in and requires a restart.

Troubleshooting Common Restore Failures

When a formal restore fails verification, the tool rolls the node back. The usual causes are a genesis blob from the wrong network, an epoch that does not exist in the bucket, or a truncated download. Re-check --network and --genesis first, then retry the same epoch; if it fails again, try --latest to distinguish a bad artifact from a bad local configuration.

When a RocksDB restore starts but the node errors on the store, inspect the directory layout under <db_path>/live and the file ownership. A nested directory or root-owned files are the most common causes. When the node starts but the checkpoint head does not advance, check peer connectivity and whether the node is still catching up from the snapshot epoch; a head that is advancing slowly is normal immediately after restore, while a head that is frozen is not. For interface-level issues after the node is healthy, the Sui gRPC guide and the Sui full node RPC endpoint setup article cover endpoint configuration.

  • Verification failure: check network, genesis blob, epoch existence, download integrity.
  • Store startup error: check <db_path>/live layout and ownership.
  • Frozen head: check peers and catch-up state before assuming corruption.

Advising Other Operators and Next Steps

Because Sui encourages community-hosted snapshots, the most useful thing an operator can do is publish clearly: which tier (Requester Pays managed versus free R2), the bucket name, the epoch range available, and the retention policy. Consumers need to know whether they can use --no-sign-request or must budget egress, and they need to know how far back the epochs go before they plan a restore.

For your own next steps, decide the node's job first, then pick the artifact type, then measure your restore with the results table above. If you are comparing self-hosting with a managed endpoint, start from the Sui networks page, review RPC pricing and the API service, and browse the OnFinality Learn hub for adjacent operational guides. For historical-serving nodes, the Sui archive nodes and historical RPC article and the Base archive node historical RPC article show how the same retention logic plays out on another chain.

  • Publish tier, bucket name, epoch range, and retention for your snapshots.
  • Choose artifact type by the queries the node must answer.
  • Measure and publish your own restore numbers with the method attached.

Never Worry about Infrastructure Again

OnFinality takes away the heavy lifting of DevOps so you can build smarter and faster.

Get Started