How the Akash Console Indexer Service Powers Real-Time Blockchain Data
The Indexer service transforms raw Akash blockchain data into structured, queryable database tables that fuel the Akash Console UI, handling schema management, message routing, per-block hooks, and in-memory caching.
The Indexer service serves as the data ingestion engine for the akash-network/console repository, continuously processing on-chain events and materializing them into relational tables. Without this service, the Console's dashboards and explorer views would lack the real-time validator, deployment, and provider statistics users rely on. By implementing a pluggable architecture around an abstract Indexer base class, the system enables modular data extraction tailored to specific Akash message types.
Core Responsibilities of the Indexer Service
The Indexer service operates through four primary functional areas, each implemented via specific methods in the abstract base class defined in apps/indexer/src/indexers/indexer.ts.
Database Schema Management
Each concrete indexer manages its own database tables through lifecycle methods that handle creation, destruction, and seeding. The abstract Indexer class requires implementations to define createTables, dropTables, and seed methods. For example, the ValidatorIndexer, MessageAddressesIndexer, and AkashStatsIndexer all override these methods to establish tables for validators, address references, and aggregate statistics respectively.
Message Dispatch and Routing
When the system processes a block, decoded protobuf messages route through the processMessage method. This method checks the msgHandlers map—populated by each concrete indexer during initialization—to find the appropriate handler for the message type. The handler executes within a benchmark timer, ensuring performance metrics are captured for every processed message.
Per-Block and Per-Transaction Hooks
Beyond individual message handling, the Indexer service supports lifecycle hooks for broader coordination. Abstract methods afterEveryTransaction and afterEveryBlock allow indexers to execute logic after each transaction or block completion. The StatsProcessor iterates over the activeIndexers array and invokes these hooks, enabling operations like account settlement, stats updates, and signer address persistence across all registered indexers.
Caching and Initialization
To prevent stale reads and optimize performance, the Indexer service implements an in-memory caching layer. The StatsProcessor calls initCache on each indexer once per run, storing the first unprocessed block height. This initialization sequence ensures that indexers can recover gracefully from failures and resume processing from the correct chain position without re-scanning historical data.
Orchestration via StatsProcessor
The StatsProcessor in apps/indexer/src/chain/statsProcessor.ts orchestrates the Indexer service by managing the flow of blockchain data from raw blocks to persistent storage. This processor handles four critical operations:
- Table Rebuilding: The
rebuildStatsTablesmethod drops and recreates all stats tables, seeds genesis data, and triggers a full reprocessing of the blockchain—functionality exposed through the Console's "re-sync" UI button. - Block Grouping: The processor queries for unprocessed blocks, groups them efficiently, and fetches raw block data using
getCachedBlockByHeight. - Message Processing: For each block, the processor iterates through transactions and messages, decodes protobuf payloads, and dispatches them to the appropriate indexer handlers via
processMessage. - Atomic Commits: The system wraps each block group in a single Sequelize transaction, ensuring that either all indexers persist their updates successfully or the entire batch rolls back to maintain data consistency.
Built-In Indexer Implementations
The apps/indexer/src/indexers/index.ts file instantiates concrete indexers and filters them based on the active chain configuration (activeChain.customIndexers). The resulting activeIndexers array determines which processors the StatsProcessor invokes for every block.
ValidatorIndexer
Defined in apps/indexer/src/indexers/validatorIndexer.ts, this indexer tracks validator metadata including creation events and edit transactions. It persists structured validator data to the Validator table, enabling the Console's validator explorer and staking interfaces.
MessageAddressesIndexer
Located in apps/indexer/src/indexers/messageAddressesIndexer.ts, this component extracts sender and receiver addresses from bank-related messages. It also records signer addresses for each transaction, populating the AddressReference table to support address-based queries and transaction history views.
AkashStatsIndexer
The apps/indexer/src/indexers/akashStatsIndexer.ts implementation aggregates deployment, lease, provider, and pricing statistics. It maintains active-lease predictions and counters that power the Console's dashboard analytics, providing real-time insights into network utilization and resource pricing.
Working with the Indexer Service
Developers interacting with the Akash Console codebase can leverage the Indexer service for both maintenance operations and custom data extraction.
Rebuilding Statistics Tables
To perform a full re-sync of blockchain data—useful after schema changes or data corruption—invoke the rebuild method:
import { statsProcessor } from '@src/chain/statsProcessor';
// Re‑create all tables and seed genesis data, then reprocess every block.
await statsProcessor.rebuildStatsTables();
Processing New Blocks
Background workers periodically call the processing method to catch up with the latest chain state:
import { statsProcessor } from '@src/chain/statsProcessor';
// Called periodically (e.g. every few seconds) to catch up with the chain.
await statsProcessor.processMessages();
Creating a Custom Indexer
To extend the system with new message handling capabilities, extend the abstract Indexer class and register the implementation:
import { Indexer } from '@src/indexers/indexer';
export class MyCustomIndexer extends Indexer {
constructor() {
super();
this.name = 'MyCustomIndexer';
this.runForEveryBlocks = false;
this.msgHandlers = {
'/my.chain.MsgDoSomething': this.handleDoSomething,
};
}
async createTables() { /* … */ }
async dropTables() { /* … */ }
async seed() { /* … */ }
private async handleDoSomething(decoded, height, tx, msg) {
// custom DB logic here
}
}
After implementing the class, register it in apps/indexer/src/indexers/index.ts and add it to the activeChain.customIndexers array to automatically participate in block processing.
Summary
- The Indexer service converts raw blockchain data into structured database tables, powering the Akash Console's real-time UI components.
- Schema management, message dispatch, lifecycle hooks, and caching form the four pillars of the indexing architecture implemented in the abstract
Indexerbase class. - StatsProcessor orchestrates all indexers, handling block grouping, message decoding, and atomic transaction commits.
- Built-in indexers cover validators (
ValidatorIndexer), address references (MessageAddressesIndexer), and network statistics (AkashStatsIndexer). - The pluggable architecture allows developers to add custom indexers by extending the base class and registering new handlers for specific protobuf message types.
Frequently Asked Questions
What is the primary function of the Indexer service in Akash Console?
The Indexer service ingests raw blockchain data from the Akash network, decodes protobuf messages, and materializes them into relational database tables. This process enables the Console UI to query real-time information about validators, deployments, leases, and providers without directly accessing the blockchain for every request.
How does StatsProcessor coordinate multiple indexers simultaneously?
The StatsProcessor maintains an activeIndexers array and iterates through it for every processed block and transaction. It calls processMessage for message handling, afterEveryTransaction post-transaction completion, and afterEveryBlock after each block, ensuring all registered indexers stay synchronized while wrapping operations in atomic database transactions.
What types of blockchain data do the built-in indexers handle?
The ValidatorIndexer processes validator creation and edit events, the MessageAddressesIndexer extracts sender, receiver, and signer addresses from financial transactions, and the AkashStatsIndexer aggregates deployment metrics, lease statistics, provider data, and pricing information used for dashboard analytics.
How can developers extend the Indexer service with custom logic?
Developers create a new class extending the abstract Indexer base class in apps/indexer/src/indexers/indexer.ts, implementing required methods like createTables, dropTables, and seed, plus message handlers in the msgHandlers map. After registering the indexer in apps/indexer/src/indexers/index.ts and adding it to the chain configuration, the StatsProcessor automatically includes it in the block processing pipeline.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →