Understanding Multichain Indexing
Multichain indexing allows you to monitor and process events from contracts deployed across multiple blockchain networks within a single indexer instance. This capability is essential for applications that:
- Track the same contract deployed across multiple networks
- Need to aggregate data from different chains into a unified view
- Monitor cross-chain interactions or state
How It Works
With multichain indexing, events from contracts deployed on multiple chains can be used to create and update entities defined in your schema file. Your indexer will process events from all configured networks, maintaining proper synchronization across chains.
Configuration Requirements
To implement multichain indexing, you need to:
- Populate the
networks
section in yourconfig.yaml
file for each chain - Specify contracts to index from each network
- Create event handlers for the specified contracts
Real-World Example: Uniswap V4 Multichain Indexer
For a comprehensive, production-ready example of multichain indexing, we recommend exploring our Uniswap V4 Multichain Indexer. This official reference implementation:
- Indexes Uniswap V4 deployments across 10 different blockchain networks
- Powers the official v4.xyz interface with real-time data
- Demonstrates best practices for high-performance multichain indexing
- Provides a complete, production-grade implementation you can study and adapt
The Uniswap V4 indexer showcases how to effectively structure a multichain indexer for a complex DeFi protocol, handling high volumes of data across multiple networks while maintaining performance and reliability.
Config File Structure for Multichain Indexing
The config.yaml
file for multichain indexing contains three key sections:
- Global contract definitions - Define contracts, ABIs, and events once
- Network-specific configurations - Specify chain IDs and starting blocks
- Contract instances - Reference global contracts with network-specific addresses
# Example structure (simplified)
contracts:
- name: ExampleContract
abi_file_path: ./abis/example-abi.json
handler: ./src/EventHandlers.js
events:
- event: ExampleEvent
networks:
- id: 1 # Ethereum Mainnet
start_block: 0
contracts:
- name: ExampleContract
address: "0x1234..."
- id: 137 # Polygon
start_block: 0
contracts:
- name: ExampleContract
address: "0x5678..."
Key Configuration Concepts
- The global
contracts
section defines the contract interface, ABI, handlers, and events once - The
networks
section lists each blockchain network you want to index - Each network entry references the global contract and provides the network-specific address
- This structure allows you to reuse the same handler functions and event definitions across networks
📢 Best Practice: When developing multichain indexers, append the chain ID to entity IDs to avoid collisions. For example:
user-1
for Ethereum anduser-137
for Polygon.
Multichain Event Ordering
When indexing multiple chains, you have two approaches for handling event ordering:
Unordered Multichain Mode (Default)
By default, the indexer processes events as soon as they're available from each chain, without waiting for other chains. This "Unordered Multichain Mode" provides better performance and lower latency.
With unordered mode (the default):
- Events will still be processed in order within each individual chain
- Events across different chains may be processed out of order
- Processing happens as soon as events are emitted, reducing latency
- You avoid waiting for the slowest chain's block time
This mode is ideal for most applications, especially when:
- Operations on your entities are commutative (order doesn't matter)
- Entities from different networks never interact with each other
- Processing speed is more important than guaranteed cross-chain ordering
Ordered Mode (Optional)
If your application requires strict deterministic ordering of events across all chains, you can enable "Ordered Mode". In this mode, the indexer synchronizes event processing across all chains, ensuring that events are processed in the exact same order in every indexer run, regardless of which chain they came from.
When to Use Ordered Mode
Use ordered mode only when:
- The exact ordering of operations across different chains is critical to your application logic
- You need guaranteed deterministic results across all indexer runs
- You're willing to accept higher latency for cross-chain consistency
Cross-chain ordering is particularly important for applications like:
- Bridge applications: Where messages or assets must be processed on one chain before being processed on another chain
- Cross-chain governance: Where decisions made on one chain affect operations on another chain
- Multi-chain financial applications: Where the sequence of transactions across chains affects accounting or risk calculations
- Data consistency systems: Where the state must be consistent across multiple chains in a specific order
How to Enable Ordered Mode
In your config.yaml:
unordered_multichain_mode: false
networks: ...
Or via environment variable:
UNORDERED_MULTICHAIN_MODE=false
Technical Details
With ordered mode enabled:
- The indexer needs to wait for all blocks to increment from each network
- There is increased latency between when an event is emitted and when it's processed
- Processing speed is limited by the block interval of the slowest network
- Events are guaranteed to be processed in the same order in every indexer run
Cross-Chain Ordering Preservation
Ordered mode ensures that the temporal relationship between events on different chains is preserved. This is achieved by:
- Global timestamp ordering: Events are ordered based on their block timestamps across all chains
- Deterministic processing: The same sequence of events will be processed in the same order every time
The primary trade-off is increased latency at the head of the chain. Since the indexer must wait for blocks from all chains to determine the correct ordering, the processing of recent events is delayed by the slowest chain's block time. For example, if Chain A has 2-second blocks and Chain B has 15-second blocks, the indexer will process events at the slower 15-second rate to maintain proper ordering.
This latency is acceptable for applications where correct cross-chain ordering is more important than real-time updates. For bridge applications in particular, this ordering preservation can be critical for security and correctness, as it ensures that deposit events on one chain are always processed before the corresponding withdrawal events on another chain.
Best Practices for Multichain Indexing
1. Entity ID Namespacing
Always namespace your entity IDs with the chain ID to prevent collisions between networks. This ensures that entities from different networks remain distinct.
2. Error Handling
Implement robust error handling for network-specific issues. A failure on one chain shouldn't prevent indexing from continuing on other chains.
3. Testing
- Test your indexer with realistic scenarios across all networks
- Use testnet deployments for initial validation
- Verify entity updates work correctly across chains
4. Performance Considerations
- Use unordered mode when appropriate for better performance
- Consider your indexing frequency based on the block times of each chain
- Monitor resource usage, as indexing multiple chains increases load
Troubleshooting Common Issues
-
Different Network Speeds: If one network is significantly slower than others, consider using unordered mode to prevent bottlenecks.
-
Entity Conflicts: If you see unexpected entity updates, verify that your entity IDs are properly namespaced with chain IDs.
-
Memory Usage: If your indexer uses excessive memory, consider optimizing your entity structure and implementing pagination in your queries.
Next Steps
- Explore our Uniswap V4 Multichain Indexer for a complete implementation
- Review performance optimization techniques for your indexer