IOTA Indexer
The IOTA Indexer is an off-fullnode service that serves data from the IOTA protocol, including both data directly generated from the chain and derivative data.
Architecture
The Indexer consists of two main components:
- Sync Worker (Writer): Pulls data from a fullnode and writes it to the database
- RPC Server (Reader): Exposes JSON-RPC APIs to query the indexed data
Key Features
- Indexer instances expose read, write, and extended JSON-RPC APIs
- Fullnodes expose read and transaction execution JSON-RPC APIs
- Validators expose only read-only JSON-RPC APIs
- Indexer sync workers require
NodeConfig::enable_rest_api flag set to true
Database Setup
Install Prerequisites
-
Install PostgreSQL server and start it
-
Install Diesel CLI:
cargo install diesel_cli --no-default-features --features postgres
Create Database
From the iota/crates/iota-indexer directory:
diesel setup --database-url="postgres://postgres:postgrespw@localhost/iota_indexer"
This creates a database named iota_indexer with default credentials:
- User:
postgres
- Password:
postgrespw
Reset Database
To wipe and recreate the database:
diesel database reset --database-url="postgres://postgres:postgrespw@localhost/iota_indexer"
Running the Indexer
Using Docker Compose (Recommended)
See pg-services-local which automatically sets up:
- Indexer Sync worker
- Indexer RPC worker
- PostgreSQL database
- Local network
Standalone Indexer Setup
Run as Writer (Sync Worker)
Pulls data from a fullnode and writes to the database:
cargo run --bin iota-indexer -- \
--db-url "postgres://postgres:postgrespw@localhost/iota_indexer" \
indexer \
--remote-store-url "http://0.0.0.0:9000/api/v1" \
--reset-db
Command-line Options:
--db-url: PostgreSQL database connection URL
--remote-store-url: Fullnode REST API URL to fetch checkpoint data
--reset-db: Reset the database before starting
Run as Reader (RPC Server)
Exposes JSON-RPC service for querying indexed data:
cargo run --bin iota-indexer -- \
--db-url "postgres://postgres:postgrespw@localhost/iota_indexer" \
json-rpc-service \
--rpc-client-url "http://0.0.0.0:9000" \
--rpc-address "0.0.0.0:9124"
Command-line Options:
--rpc-client-url: Fullnode RPC URL for transaction execution
--rpc-address: Address to bind the JSON-RPC server (default: 0.0.0.0:9124)
Testing the Connection
Query the indexer via JSON-RPC:
curl http://localhost:9124 \
--header 'content-type: application/json' \
--data '{
"jsonrpc": "2.0",
"id": 1,
"method": "iota_getChainIdentifier"
}'
Important Notes
To have a fully functional indexer, you need to run both components:
- Writer instance to populate the database with data from the fullnode
- Reader instance to expose the API
Running only the reader will not provide data unless the database has been populated by a writer.
Backfilling Data
When schema changes require backfilling historical data:
Usage: iota-indexer run-backfill [OPTIONS] <START> <END> <COMMAND>
Commands:
sql Run a SQL backfill
ingestion Run a backfill driven by the ingestion engine
Arguments:
<START> Start of the range to backfill (inclusive)
<END> End of the range to backfill (inclusive)
Options:
--max-concurrency <MAX_CONCURRENCY> Maximum concurrent tasks [default: 10]
--chunk-size <CHUNK_SIZE> Data chunks per task [default: 1000]
Backfill Options
SQL Backfill: Executes SQL statements directly against the database in chunks
Ingestion Backfill: Fetches checkpoint data from an ingestion source. Supported sources:
--data-ingestion-path <DIR>: Path to directory containing .chk files
--remote-store-url <URL>: Remote store URL (e.g., http://0.0.0.0:9000/api/v1)
--rpc-client-url <URL>: RPC client URL (e.g., http://0.0.0.0:9000)
Example: Backfill tx-wrapped-or-deleted-objects Table
cargo run --bin iota-indexer -- \
--database-url <DATABASE_URL> \
run-backfill <START> <END> \
ingestion tx-wrapped-or-deleted-objects \
--remote-store-url <REMOTE_STORE_URL>
Error Handling
If a backfill fails, restart from:
restart_from = failed_chunk_start - (max_concurrency * chunk_size)
CLI Reference
The indexer is transitioning from old CLI to new CLI. Both are currently supported:
# Old CLI (deprecated)
cargo run --bin iota-indexer -- help-deprecated
# New CLI (recommended)
cargo run --bin iota-indexer -- help
Experimental Features
Historic Fallback (REST KV Store)
Experimental feature subject to change without notice.
The --fallback-kv-url flag enables fallback to a REST KV store for historical data when not available in the primary database. This depends on the iota-rest-kv crate API, which is still being finalized.
Environment Variables
IOTA Indexer Variables
The indexer supports the following environment variables for tuning performance and behavior:
Database Connection:
DB_POOL_SIZE - Database connection pool size (default: 100)
DB_CONNECTION_TIMEOUT - Connection timeout in seconds (default: 30)
DB_STATEMENT_TIMEOUT - SQL statement timeout in seconds (default: 3600)
Checkpoint Processing:
DOWNLOAD_QUEUE_SIZE - Checkpoint download queue size (default: 200)
INGESTION_READER_TIMEOUT_SECS - Ingestion timeout (default: 20)
CHECKPOINT_PROCESSING_BATCH_DATA_LIMIT - Batch data limit in bytes (default: 20000000)
Snapshots:
OBJECTS_SNAPSHOT_MIN_CHECKPOINT_LAG - Minimum lag for snapshots (default: 300)
Pruning:
EPOCHS_TO_KEEP - Number of epochs to retain during pruning
OPTIMISTIC_PRUNER_BATCH_SIZE - Batch size for optimistic pruning
Fallback KV Store:
FALLBACK_KV_MULTI_FETCH_BATCH_SIZE - Multi-fetch batch size (default: 100)
FALLBACK_KV_CONCURRENT_FETCHES - Concurrent fetch operations (default: 10)
FALLBACK_KV_CACHE_SIZE - KV cache size (default: 100000)
PostgreSQL Variables
The indexer also respects standard PostgreSQL environment variables:
PGHOST: Database host
PGPORT: Database port
PGUSER: Database user
PGPASSWORD: Database password
PGDATABASE: Database name
Running Tests
Start Test Database
docker run --name iota-indexer-tests \
-e POSTGRES_PASSWORD=postgrespw \
-e POSTGRES_USER=postgres \
-e POSTGRES_DB=iota_indexer \
-d -p 5432:5432 postgres
Run Tests
# PostgreSQL integration tests (sequential)
cargo test --features pg_integration -- --test-threads 1
# RPC tests with shared runtime
cargo test --profile simulator --features shared_test_runtime
# Using nextest (faster)
cargo nextest run --features pg_integration --test-threads 1