A blockchain indexer processes raw blockchain data into a queryable database, enabling fast custom queries that raw node RPC calls can't efficiently support. This guide covers building a basic indexer setup.
Why Raw Node RPC Isn't Sufficient for Complex Queries
A blockchain node's RPC interface is designed for basic operations (checking a specific address, submitting a transaction) — it's not built for complex analytical queries (all transactions above a certain value in a date range, aggregated statistics across many addresses); an indexer bridges this gap.
The Basic Indexer Architecture
Blockchain Node -> Indexer Process -> Structured Database -> Query API
The indexer continuously processes new blocks as they arrive, extracting and storing relevant data in a queryable format (typically a relational or specialized database), which your application then queries directly rather than hitting the node's RPC for complex questions.
Step 1 — Set Up a Database for Indexed Data
CREATE TABLE transactions (
txid VARCHAR(64) PRIMARY KEY,
block_height INT,
from_address VARCHAR(64),
to_address VARCHAR(64),
amount DECIMAL(20,8),
timestamp TIMESTAMP
);
See How to Write and Optimize SQL Queries: Indexing Basics for general database indexing principles, applied specifically here — ensure your schema has appropriate indexes for the query patterns you actually need to support.
Step 2 — Build the Indexing Process
import requests
def index_block(height):
block = rpc_call("getblock", [get_block_hash(height), 2])
for tx in block['tx']:
store_transaction(tx, height)
current_height = get_last_indexed_height()
chain_tip = rpc_call("getblockcount")
for height in range(current_height + 1, chain_tip + 1):
index_block(height)
Processes blocks sequentially from where indexing last left off, extracting and storing the specific data your application needs.
Step 3 — Handle Chain Reorganizations
def check_for_reorg(height):
stored_hash = get_stored_block_hash(height)
current_hash = rpc_call("getblockhash", [height])
if stored_hash != current_hash:
rollback_and_reindex_from(height)
Blockchain reorganizations (the chain "rewriting" recent history due to a competing longer chain) require your indexer to detect and correctly handle this, rolling back and re-indexing affected blocks — a genuinely important correctness consideration often overlooked in naive indexer implementations.
Step 4 — Run the Indexer Continuously
[Unit]
Description=Blockchain Indexer
[Service]
ExecStart=/usr/bin/python3 /opt/indexer/index.py
Restart=always
Run as a persistent service, continuously catching up to and following the chain tip as new blocks arrive.
Building a Query API on Top of Indexed Data
See How to Build and Secure a REST API on a VPS for the general API-building pattern — once data is indexed, build an API exposing the specific queries your application needs, benefiting from the database's query performance rather than repeatedly hitting node RPC.
Considering Existing Indexer Solutions
Depending on your specific chain and needs, established open-source indexer projects may already exist and be more mature than a custom-built solution — evaluate whether an existing project genuinely fits your needs before building entirely from scratch.
Monitoring Indexer Health and Sync Lag
Track the gap between your indexer's last processed block and the actual current chain tip — a growing lag indicates your indexer isn't keeping up with chain growth, warranting investigation before it becomes a genuine data-freshness problem for your application.
Common Errors
Indexed data shows inconsistencies after a chain reorg — confirms your reorg handling logic has a gap; review and strengthen the detection/rollback mechanism, since this is a common source of subtle indexer correctness bugs that only manifest during actual reorganization events.
Continue Reading
- How to Run a Local Blockchain Explorer
- How to Build and Secure a REST API on a VPS
- How to Write and Optimize SQL Queries: Indexing Basics
Browse more articles in Cryptocurrency & Blockchain Node Hosting.