Blockchain applications rely on several technical components that handle different aspects of blockchain interaction, such as indexers, RPC servers, and relayers. These components are crucial as they address the three temporal dimensions of blockchain applications:
- The Past: Event indexing and historical data processing
- The Present: Real-time state queries and current blockchain state access
- The Future: Transaction execution and state modifications
This article explores how we’ve structured our blockchain application architecture. For more details about our smart contract design, you can read our previous article.
Our main goals at Spiko are to operate efficiently across all our networks and to easily extend on-chain capabilities, whether that means adding new tokens or expanding to a new network.
Design choices
Like many software architecture decisions, we had to choose which building blocks to rely on when developing these components. Several off-the-shelf solutions exist, including:
- The Graph for indexing via subgraphs
- Etherscan API for real-time state access
- OpenZeppelin Relayer for transaction relaying
Initially, we chose these ready-made solutions to move faster. However, the main pain points we encountered were that these solutions weren’t robust or available for all the networks we operate on. For example, more than 75% of our calls to The Graph were failing on the Etherlink network.
At Spiko, issuing, operating, and monitoring our tokens is our core mission. We decided to take control back and implement a robust, scalable system. Its main goal is to handle the complexity of multi-chain operations across EVM networks (Ethereum, Polygon, Base, Arbitrum), Starknet, and Stellar. Our architecture relies solely on RPC servers for each network, maintaining minimal external dependencies while maximizing flexibility.
Event Indexing and Historical Data
Each of our smart contracts emits events on each chain, especially the different token contracts (EUTBL, USTBL, etc.) and the redemptions contract. We need to monitor these events, such as transfer events, to keep track of the complete state of our tokens as we operate with both custodial and non-custodial wallets.
Our indexer continuously monitors blockchain activity across our different smart contracts. We regularly index the latest blocks for each contract on every network we operate on. The indexer generates queryable, structured data from the immutable blockchain history that can be used throughout all our applications.
The indexing process follows a contract-based approach that remains consistent across all supported chains:
- Block Range Processing: The indexer processes blocks in configurable ranges to optimize performance and reduce RPC load
- Multiple RPC Queries: We use several RPC endpoints in parallel to prevent RPC failures or incomplete responses
- Event Deduplication: Prevents duplicate event processing using a composite key of block number, log index, and transaction hash
- Event Storage: Stores structured event data in our database with proper indexing for efficient querying
This standardized approach to indexing allows us to easily scale our indexer across new tokens or networks.

Real-Time State Queries
Our RPC system provides a unified interface for querying current blockchain state across all supported networks. This is particularly crucial for real-time operations such as:
- Balance queries for our ERC20 tokens (and equivalent tokens on other chains)
- Total supply verification across networks
For current data, we always rely on real-time on-chain data. This abstraction layer allows our application to interact with different blockchains using consistent patterns, significantly reducing development complexity when supporting multiple networks.
Transaction Execution and Relaying
Our relayer system handles the execution of transactions across different blockchain networks. While each network has its own relayer implementation to handle network-specific requirements, they all follow consistent patterns for transaction management.
Our system manages the complete transaction lifecycle:
- Transaction Creation: Converts business operations into properly formatted blockchain transactions
- Nonce Management: Guarantees transaction idempotence and proper sequential ordering
- Gas Estimation: Calculates appropriate gas fees based on network conditions
- Transaction Signing: Secures transaction signing using a managed wallet from Dfns
- Broadcasting: Sends transactions to the respective network
- Monitoring: Tracks transaction status, confirmations, and potential failures
We actively monitor transactions that remain in the mempool beyond expected timeframes. When detected, we implement a fee-bumping strategy by resubmitting the transaction with the same nonce but higher gas fees, ensuring timely execution.

Final Thoughs
These three components (indexing, real-time queries, and transaction execution) form the foundation of most blockchain-intensive applications. At Spiko, this architecture serves as core infrastructure for all blockchain data access and manipulation.
What have we gained? Significantly fewer bugs, particularly in our indexer which now maintains a 99%+ success rate compared to 25% with The Graph on certain networks. Our custom relayer is also faster than external alternatives improving the user experience during minting, token transfers and redemptions.
The biggest win has been new network implementation speed. Launching Spiko on a new blockchain now takes several weeks instead of several months. Our standardized approach requires only network-specific configuration rather than architectural reimplementation.