Skip to main content

Running the Archival Store and Service

The Archival Store and Service are part of the Sui data access infrastructure. The stack provides long-term storage and low-latency point lookups of historical onchain data through a gRPC service backed by Google Cloud Bigtable. This stack is optimized for operators and data providers who need to serve historical transactions, checkpoints, objects, and epoch data beyond the retention horizon of full nodes or indexer databases.

The Archival Service exposes the same gRPC LedgerService API as a Sui full node, so existing gRPC clients can query it by changing the endpoint. The service is powered by an indexer (sui-kvstore-alt) that reads checkpoints from the remote checkpoint store and writes processed data to Bigtable, and a gRPC server (sui-kv-rpc) that reads from Bigtable to serve client requests.

See Archival Store and Service for more information on the stack.

Architecture overview

  1. Google Cloud Bigtable: The backing store that holds all historical chain data across 14 tables.
  2. sui-kvstore-alt (Indexer): Reads checkpoints from the remote checkpoint store and writes processed data to Bigtable.
  3. sui-kv-rpc (Archival Service): A gRPC server that reads from Bigtable and exposes the LedgerService API to clients.
  • A Google Cloud Platform (GCP) project with the Bigtable API enabled.
  • Two GCP service accounts:
    • Read/write account for the indexer; requires roles/bigtable.user.
    • Read-only account for the gRPC service; requires roles/bigtable.reader.
  • A checkpoint bucket for your network, for history:
    • Mainnet: --remote-store-gcs mysten-mainnet-checkpoints-use4 (Requester Pays).
    • Testnet: --remote-store-gcs mysten-testnet-checkpoints-use4 (Requester Pays).
  • A Sui full node with gRPC enabled, for the tip.

Authentication

Both binaries authenticate to GCP using Application Default Credentials (ADC), for both Bigtable and GCS.

On GKE: Use Workload Identity. No keys or environment variables needed.

Outside GKE: Point GOOGLE_APPLICATION_CREDENTIALS at a service account JSON key file:

export GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json

The public HTTPS endpoints (https://checkpoints.mainnet.sui.io, https://checkpoints.testnet.sui.io) keep only the latest 30 days. Use the GCS buckets above for backfill.

Bigtable setup

Create a Bigtable instance

Create a Bigtable instance in your GCP project. See the Bigtable documentation.

SettingRecommendation
Storage typeSSD. HDD is untested and not recommended.
Node countEnable autoscaling. See Scaling.

Do not use Bigtable replication for this deployment. Run a separate Bigtable instance, sui-kvstore-alt indexer, and sui-kv-rpc service in each region.

Create tables

Create these 14 tables, each with a single column family sui and maxversions=1:

TableDescription
checkpointsCheckpoint summaries, signatures, and contents
checkpoints_by_digestCheckpoint lookup by digest
transactionsTransaction data, effects, events, and balance changes
objectsObject data keyed by object ID and version
epochsEpoch start and end data including system state
watermark_altInternal indexer watermark tracking
protocol_configsProtocol configuration per epoch
packagesPackage metadata keyed by original ID and version
packages_by_idPackage lookup by ID
packages_by_checkpointPackage lookup by checkpoint
system_packagesSystem package data
tx_seq_digestTransaction sequence number to digest. Backs the List APIs
transaction_bitmap_indexBitmap index over transaction filters
event_bitmap_indexBitmap index over event filters
for table in checkpoints checkpoints_by_digest transactions objects epochs \
watermark_alt protocol_configs packages packages_by_id \
packages_by_checkpoint system_packages tx_seq_digest \
transaction_bitmap_index event_bitmap_index; do
cbt -project <GCP_PROJECT> -instance <INSTANCE_ID> createtable "$table"
cbt -project <GCP_PROJECT> -instance <INSTANCE_ID> createfamily "$table" sui
cbt -project <GCP_PROJECT> -instance <INSTANCE_ID> setgcpolicy "$table" sui maxversions=1
done

Storage requirements

Measured 2026-07-27. Grows with network activity.

TableMainnetTestnet
transactions10.8 TB3.2 TB
objects5 TB1.3 TB
checkpoints947.7 GB572.9 GB
transaction_bitmap_index606.7 GB311.6 GB
tx_seq_digest502.5 GB335.5 GB
event_bitmap_index250.9 GB21.3 GB
checkpoints_by_digest18.2 GB21.8 GB
epochs169.2 MB156.1 MB
packages30.9 MB71 MB
watermark_alt23.5 MB41.5 MB
packages_by_id19.1 MB43.2 MB
packages_by_checkpoint16.5 MB38.1 MB
protocol_configs1.2 MB610.2 KB
system_packages1.6 KB2.9 KB
Total~18.1 TB~5.8 TB

Scaling

Use autoscaling. The indexer paces its own writes, so the cluster grows during backfill and settles back at the tip on its own.

Autoscaling settingMainnetTestnet
Minimum nodes73
Maximum nodes3010
CPU utilization target60%60%

Each SSD node holds up to 5 TB; stay under 70% (3.5 TB per node).

Backup policy

Configure automated backups. Daily with 7-day retention is a reasonable default. See the Bigtable backup documentation.

Indexer setup

sui-kvstore-alt reads checkpoints and writes to Bigtable through 14 pipelines.

CPUMemory
At the tip1 core1 GB
Backfilling16 cores32 GB

Run sui-kvstore-alt

sui-kvstore-alt \
--chain mainnet \
my-bigtable-instance \
--remote-store-gcs mysten-mainnet-checkpoints-use4 \
--streaming-url http://my-fullnode:9000

For Testnet, use --chain testnet with --remote-store-gcs mysten-testnet-checkpoints-use4.

That one command backfills from genesis and then indexes at the tip. There is no separate backfill config and no cutover. Do not set --rpc-api-url.

CLI parameterRequiredDescription
<INSTANCE_ID>YesBigtable instance ID. Positional.
--chainYesmainnet, testnet, or unknown.
--remote-store-gcsYesGCS bucket to read checkpoint history from.
--streaming-urlNoFullnode gRPC URL for live checkpoints. Use it.
--configNoTOML config path. Omit it. See Indexer configuration.
--rpc-api-urlNoRead history from a fullnode instead of a bucket. Alternative to --remote-store-gcs, not an addition.
--remote-store-urlNoHTTPS checkpoint store. Alternative to --remote-store-gcs.
--remote-store-headerNoRepeatable Name:Value header for remote-store requests.
--rpc-username / --rpc-passwordNoCredentials for --rpc-api-url.
--checkpoint-timeout-msNoPer-checkpoint download timeout. Default 120000.
--checkpoint-connection-timeout-msNoCheckpoint-store connection timeout. Default 120000.
--bigtable-projectNoGCP project ID. Defaults to the credentials' project.
--app-profile-idNoBigtable app profile. Must be single-cluster routing.
--bigtable-max-decoding-message-sizeNoMax decoded gRPC response, bytes. Default 33554432.
--pipelineNoRepeatable pipeline name. Omit to run all 14.
--first-checkpointNoStart checkpoint for pipelines with no watermark. Default 0.
--last-checkpointNoInclusive stop checkpoint.
--metrics-addressNoPrometheus bind address. Default 0.0.0.0:9184.
--write-legacy-dataNoDo not set this.

Exactly one checkpoint source is allowed (--remote-store-gcs, --remote-store-url, --rpc-api-url, and so on); passing two is a startup error. --streaming-url is not one of them and runs alongside whichever you pick.

info

Mysten Labs plans to enable requester-pays on the public checkpoint buckets in the future. Streaming from your own full node avoids these costs.

Indexer configuration

--config takes an optional TOML file. You do not need one. The tables below are reference only.

Adaptive write rate limiting

The indexer paces its own Bigtable writes from the RateLimitInfo directives Bigtable returns on every MutateRows response, combined with observed write latency. This is on by default and replaces manual rate-limit sizing.

  • The unit is MutateRows requests per second, not rows. Each request carries up to max-rows rows (default 100).
  • It starts at 10 requests per second.
  • It grows only when the directive is positive, latency is healthy, and the indexer is driving at least 80% of the current limit.
  • It cuts to 0.7x on a severe latency observation or a DeadlineExceeded, Unavailable, or ResourceExhausted response.

It requires a single-cluster-routing app profile. Disable it only if you cannot provide one:

batch-write-flow-control = false

Top-level options

OptionDefaultDescription
batch-write-flow-controltrueAdaptive write rate limiting.
total-max-rows-per-secondunlimitedStatic global rate limit, rows/sec. Leave unset; it starves the adaptive controller.
max-rows-per-secondunlimitedStatic per-pipeline rate limit, rows/sec. Leave unset.
bigtable-channel-timeout-ms60000Channel-level Bigtable gRPC timeout.
bigtable-connection-pool-sizeN/ADeprecated. Use [bigtable-pool].

Connection pool ([bigtable-pool])

OptionDefaultDescription
initial-pool-size10Channels created at startup.
min-pool-size1Minimum channels.
max-pool-size200Maximum channels.
min-rpcs-per-channel5Load below which the pool scales down.
max-rpcs-per-channel50Load above which the pool scales up.
max-resize-delta2Max channels removed per scale-down.
downscale-threshold3Low-load observations before scaling down.
maintenance-interval-ms60000Time between maintenance cycles.
refresh-age-ms2700000Channel age before refresh (45 min).
refresh-jitter-ms300000Jitter on refresh age (5 min).

Committer ([committer])

OptionDefaultDescription
write-concurrency256Concurrent write tasks per pipeline.
collect-interval-ms500How often to flush buffered rows.
watermark-interval-ms500How often to update the watermark.
watermark-interval-jitter-ms0Jitter on the watermark interval.

Per-pipeline overrides ([pipeline.<name>])

Section names drop the kvstore_ prefix and use kebab-case, except epoch-start and epoch-end, and the bitmap pipelines, which are transaction-bitmap-index and event-bitmap-index.

OptionDefaultDescription
max-rows100Max rows per Bigtable write request.
max-rows-per-secondunlimitedPer-pipeline rate limit. Leave unset.
committer.*N/AAny committer field, per pipeline.

See Pipeline architecture: Performance tuning for the remaining framework options.

Pipelines

All 14 are required for full archival service functionality.

PipelineTarget tableType
kvstore_checkpointscheckpointsConcurrent
kvstore_checkpoints_by_digestcheckpoints_by_digestConcurrent
kvstore_transactionstransactionsConcurrent
kvstore_objectsobjectsConcurrent
kvstore_epochs_startepochsConcurrent
kvstore_epochs_endepochsConcurrent
kvstore_protocol_configsprotocol_configsConcurrent
kvstore_packagespackagesConcurrent
kvstore_packages_by_idpackages_by_idConcurrent
kvstore_packages_by_checkpointpackages_by_checkpointConcurrent
kvstore_system_packagessystem_packagesConcurrent
kvstore_tx_seq_digesttx_seq_digestConcurrent
kvstore_transaction_dimensionstransaction_bitmap_indexSequential
kvstore_event_dimensionsevent_bitmap_indexSequential

Backfill

Start the indexer without --first-checkpoint. A full Mainnet backfill takes approximately 3-4 days on a 30-node SSD cluster with a 16 CPU indexer.

Use one indexer instance. One instance can drive a 30-node cluster, the largest scale tested.

Bigtable writes are idempotent, so you can run several instances at the tip for rolling deployments.

Archival service setup

sui-kv-rpc is a gRPC server that reads from Bigtable and exposes the LedgerService API.

Run sui-kv-rpc

sui-kv-rpc --config /etc/sui-kv-rpc/config.toml

instance-id is the only required setting:

instance-id = "my-bigtable-instance"
address = "[::]:8000"
metrics-host = "0.0.0.0"
credentials = "/etc/sui-kv-rpc/bigtable-ro-sa.json"
tls-cert = "/secrets/cert.pem"
tls-key = "/secrets/key.pem"
enable-list-apis = true

Run sui-kv-rpc --config-schema to print the full JSON Schema with per-field documentation.

Configuration reference

SettingDefaultDescription
instance-idnoneRequired. Bigtable instance ID.
address[::1]:8000gRPC listen address.
metrics-host127.0.0.1Prometheus bind host. Set 0.0.0.0 to be scrapable.
metrics-port9184Prometheus bind port.
credentialsADCService account JSON key path.
bigtable-projectcredentials' projectGCP project ID.
app-profile-idnoneBigtable app profile ID.
tls-cert / tls-keynonePEM cert and key. TLS activates only when both are set.
bigtable-channel-timeout-ms60000Channel-level Bigtable gRPC timeout.
bigtable-initial-pool-size10Channels created at startup.
bigtable-min-pool-size1Minimum channels.
bigtable-max-pool-size200Maximum channels.
enable-list-apisfalseServe the three List APIs. Requires the tx_seq_digest and both bitmap pipelines.
request-bigtable-concurrency50Per-request cap on concurrent Bigtable operations.
ledger-historysee belowList API tuning.
stagessee belowRead concurrency tuning.

The old positional and flag form (<INSTANCE_ID>, <ADDRESS>, --credentials, --tls-cert, and so on) still works, takes precedence over the config file, and logs a deprecation warning. Use the config file.

List API tuning ([ledger-history])

Only used when enable-list-apis = true. The [ledger-history.list-transactions], [ledger-history.list-events], and [ledger-history.list-checkpoints] tables each take timeout-ms (default 30000), default-limit-items, max-limit-items, and render-ahead (default 4).

Methoddefault-limit-itemsmax-limit-items
list-transactions50500
list-events501000
list-checkpoints1050

The [ledger-history] table takes bitmap-bucket-budget-tx (4000), bitmap-bucket-budget-event (4000), max-bitmap-filter-literals (10), and bitmap-drain-probe-rows (50).

Read stages ([stages.<name>])

The [stages.tx-seq-digest], [stages.transactions], [stages.objects], and [stages.checkpoints] tables each take chunk-size (default 100) and concurrency.

StageDefault concurrency
tx-seq-digest10
transactions25
objects50
checkpoints10

gRPC API

Same LedgerService API as a Sui full node, so existing gRPC clients work by changing the endpoint URL. Server reflection is enabled.

MethodDescriptionLimit
GetServiceInfoChain ID, current epoch, latest checkpoint, server version.N/A
GetObjectObject by ID, optionally at a version.N/A
BatchGetObjectsBatch object lookup. Requires exact versions.1000
GetTransactionTransaction by digest.N/A
BatchGetTransactionsBatch transaction lookup.200
GetCheckpointCheckpoint by sequence number or digest.N/A
GetEpochEpoch data by epoch number.N/A
ListTransactionsStreaming transaction listing, optionally filtered.50 default, 500 max
ListEventsStreaming event listing, optionally filtered.50 default, 1000 max
ListCheckpointsStreaming checkpoint listing, optionally filtered.10 default, 50 max

The three List methods return Unimplemented unless enable-list-apis = true. There are no subscription RPCs. Every method except GetServiceInfo supports read_mask.

Health check

GET /health on port 8081.

tip

Production hardening checklist:

  • Least-privilege service accounts. roles/bigtable.user for the indexer, roles/bigtable.reader for the service. Do not share one account.
  • Credentials in a secret manager. Prefer Workload Identity on GKE over key files.
  • Test backup and restore. Configure Bigtable backups and verify you can restore, not just that backups exist.
  • TLS. Set tls-cert and tls-key, and restrict the gRPC and health endpoints to trusted networks.
  • Single-cluster-routing app profile for the indexer. Nothing validates this at runtime.

See Security Best Practices.

Monitoring

Both binaries export Prometheus metrics on port 9184 at /metrics.

The indexer exports the standard indexer framework metrics with a kvstore_alt_ prefix, so existing Postgres indexer dashboards apply.

scrape_configs:
- job_name: sui-kvstore
static_configs:
- targets: ['<INDEXER_HOST>:9184']
- job_name: sui-kv-rpc
static_configs:
- targets: ['<RPC_HOST>:9184']

Write flow-control metrics

MetricTypeDescription
kv_bt_flow_control_effective_qpsgaugeCurrent admitted MutateRows requests per second.
kv_bt_flow_control_last_observation_start_qpsgaugeActual request rate last window. Well below effective_qps means the indexer is not demand-limited.
kv_bt_flow_control_write_latency_window_avg_msgaugeTen-second average write latency.
kv_bt_flow_control_write_latency_baseline_msgaugeLearned healthy-latency baseline.
kv_bt_flow_control_throttle_mshistogramTime each write waited for admission.
kv_bt_flow_control_events_totalcounterLifecycle events, labeled event.

The bitmap pipelines export bitmap_watermark_lag_ms_*, bitmap_write_chunk_latency_seconds_*, bitmap_write_retry_rows_total_*, bitmap_row_key_size_bytes_*, and bitmap_serialized_bitmap_size_bytes_*, suffixed with the pipeline name rather than labeled.

Archival service metrics

MetricTypeDescription
rpc_request_latencyhistogramEnd-to-end request latency.
rpc_request_handler_latencyhistogramHandler latency, by path.
rpc_first_chunk_latencyhistogramTime to first streamed chunk, by path.
rpc_requestscounterRequest count, by status.
rpc_inflight_requestsgaugeConcurrent requests in flight, by path.
kv_get_latency_mshistogramBigtable read latency per batch request.
kv_get_latency_ms_per_keyhistogramBigtable read latency divided by batch size.
kv_scan_latency_mshistogramBigtable scan latency.
kv_bt_chunk_latency_mshistogramBigtable processing time per response chunk.
kv_get_successcounterSuccessful Bigtable reads.
kv_get_not_foundcounterBigtable reads that found no row.
kv_get_errorscounterFailed Bigtable reads.
kv_scan_successcounterSuccessful Bigtable scans.
kv_rpc_response_render_latency_mshistogramResponse render latency.
kv_rpc_response_page_byteshistogramRendered page size.
kv_rpc_stream_first_frame_latency_mshistogramTime to first frame of a List response.
kv_rpc_bitmap_buckets_evaluatedhistogramBitmap buckets evaluated per query.
kv_rpc_bitmap_buckets_discardedhistogramBitmap buckets discarded per query.
kv_rpc_bigtable_permit_wait_mshistogramWait for a per-request Bigtable permit.
bt_pool_pool_sizegaugeChannels in the connection pool.
bt_pool_channels_replacedcounterChannels replaced due to age refresh.
bt_pool_rpcs_completedcounterRPCs completed through the pool.
thread_stall_duration_sechistogramTokio thread stall duration.

The kv_* read metrics are labeled client and table.

EnvironmentRUST_LOG
Productioninfo
Debugginginfo,sui_kvstore=debug,sui_indexer_alt_framework=debug