A high-performance Substrate blockchain indexer
Features • Quick Start • Documentation • Architecture • Contributing
Maestro is a fast, modular blockchain indexer for Substrate-based chains. It subscribes to finalized blocks, decodes extrinsics and events, and exposes the data through a GraphQL API.
Built with a plugin architecture, Maestro makes it easy to add custom indexing logic for any pallet without modifying the core codebase.
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Substrate Node │────▶│ Maestro │────▶│ PostgreSQL │
│ (WebSocket) │ │ (Indexer) │ │ │
└─────────────────┘ └────────┬────────┘ └─────────────────┘
│
▼
┌─────────────────┐
│ GraphQL API │
│ (Port 4000) │
└─────────────────┘
- Real-time Indexing — Subscribes to finalized blocks via WebSocket for instant updates
- GraphQL API — Query blocks, extrinsics, and events with a powerful, typed API
- Plugin System — Add custom handlers for any pallet with the bundle architecture
- Reorg Handling — Automatically handles chain reorganizations
- Prometheus Metrics — Built-in metrics for monitoring and alerting
- Type-Safe — Written in Rust with compile-time guarantees
- Rust 1.75+
- PostgreSQL 14+
- A running Substrate node
# Clone the repository
git clone https://github.com/allfeat/maestro.git
cd maestro
# Build in release mode
cargo build --release# Start PostgreSQL (using Docker)
docker-compose up -d
# Run the indexer
./target/release/maestro \
--ws-url ws://localhost:9944 \
--database-url postgres://maestro:maestro@localhost:5432/maestroThe GraphQL playground will be available at http://localhost:4000/graphql.
query {
blocks(first: 5) {
edges {
node {
number
hash
timestamp
extrinsicCount
eventCount
}
}
}
}Maestro can be configured via CLI arguments or environment variables:
| Option | Environment | Default | Description |
|---|---|---|---|
--ws-url |
WS_URL |
ws://127.0.0.1:9944 |
Substrate node WebSocket URL |
--database-url |
DATABASE_URL |
postgres://localhost/maestro |
PostgreSQL connection string |
--graphql-port |
GRAPHQL_PORT |
4000 |
GraphQL server port |
--metrics-port |
METRICS_PORT |
9090 |
Prometheus metrics port |
--log-level |
LOG_LEVEL |
info |
Log verbosity |
--block-mode |
BLOCK_MODE |
finalized |
Subscription mode (finalized/best) |
# Run database migrations only
maestro --migrate-only
# Purge all indexed data (restart from genesis)
maestro --purge
# Purge without confirmation (for scripts)
maestro --purge -yMaestro follows a hexagonal (ports & adapters) architecture:
bin/maestro/ # CLI and service orchestration
crates/
├── core/ # Domain models, ports (traits), business logic
├── substrate/ # Substrate RPC adapter
├── storage/ # PostgreSQL adapter
├── graphql/ # GraphQL API server
└── handlers/ # Pallet-specific handler bundles
Bundles are the extension point for custom indexing logic. Each bundle can:
- Define its own database schema via migrations
- Register handlers for specific pallets
- Expose custom GraphQL queries
impl HandlerBundle for MyBundle {
fn name(&self) -> &'static str { "my_bundle" }
fn handlers(&self) -> Vec<Arc<dyn PalletHandler>> {
vec![Arc::new(MyHandler::new(self.storage.clone()))]
}
fn migrations(&self) -> &'static [&'static str] {
&[include_str!("migrations/001_init.sql")]
}
}See the handlers documentation for a complete guide.
Benchmarks on commodity hardware (AMD Ryzen 5, 32GB RAM, NVMe SSD):
| Metric | Value |
|---|---|
| Indexing speed | ~500 blocks/sec (historical sync) |
| Query latency | <10ms (p99) |
| Memory usage | ~200MB (steady state) |
Contributions are welcome! Please read our Contributing Guide before submitting a PR.
# Run tests
cargo test
# Run linter
cargo clippy --all -- -D warnings
# Format code
cargo fmtNote: The core indexer and the Balances handler have been tested on a Substrate chain running polkadot-stable2509 (Polkadot SDK). Compatibility with other versions is not guaranteed and may require adjustments. If you encounter issues with a different runtime version, please open an issue.
Best block mode: When using
--block-mode best, blocks may be reorged. The indexer will automatically detect and reindex affected blocks, but data may temporarily be inconsistent during reorgs.
This project was developed with the assistance of Large Language Models (LLMs), specifically Claude by Anthropic. While all code has been reviewed and tested, please report any issues you encounter.
Maestro is licensed under the Apache License 2.0.