We recommend checking the NEAR Data Flow to familiarize yourself with how data flows within the NEAR ecosystem.
Blockchains and their nature
Blockchain data is optimized for serialized writes, one block at a time, as the chain is being created. Querying the blockchain for data about a specific block or account is fairly straightforward, as only the data for a specific block needs to be retrieved. However, querying data across many blocks (e.g.all transfers between date X and Y) can be cumbersome because we have to aggregate results from multiple single-block queries.
Given the fact that a blockchain itself is a distributed database, and a smart contract (decentralized application, dApp) is an application that runs on a virtual machine inside a blockchain, we need to understand that smart contracts should not be considered as a “backend”. While some applications might consist only of smart contracts, building a dApp with only smart contracts, in most cases, is not possible.
Smart contracts are limited in terms of interactions. By “interactions” we mean things that are very common in the real world, like user notifications, integration with third-party applications, etc.
However, the nature of a blockchain is that it must be deterministic. A critical feature of a blockchain is that it knows the state at a given time, and for blockchains that time unit is a block. Think of them as being snapshots. A blockchain does snapshots of its state on every block. We as users can call smart contracts for a specific block, and the blockchain provides guarantees that execution will always produce the same result for the same block any time we call it.
The deterministic nature of a blockchain closes it from external (off-chain) variables. It is totally impossible to perform a call to an API from within a smart contract. A blockchain and a smart contract are closed off from the external (off-chain) world.
Blockchains are great at providing a way to apply the requested changes to the state in a decentralized manner. However, in order to observe the changes, you need to actively pull the information from the network.
Instead of abstract explanations let’s look at an example.
Example dApp: Say, we have a smart contract that sells e-books. Once a user buys a book we want to send them a copy via email.
Getting the data from a blockchain from the external world
NEAR blockchain implements a JSON-RPC endpoint for everyone to interact with the blockchain. Through the JSON-RPC API users can call smart contracts triggering them to be executed with given parameters. Also, users can view the data from the blockchain. So, continuing with our example we can make our helper pull a Block every second, then pull all the Chunks and analyze the Transactions included in the Block to check if there is a transaction to our smart contract with “buy an e-book” function call. If we observe such a Transaction, we need to ensure it is successful, so we don’t send the e-book to a user whose “buy e-book” Transaction failed. After the process is complete we can trigger the helper’s code to send the user an email with the e-book they bought. This approach is so-called pull model of getting the data. There is nothing wrong with this approach, but sometimes you might find it is not the most comfortable or reliable approach. Also, not all the data is available through the JSON-RPC. Local Receipts for example are not available through the JSON-RPC, because they are not stored in NEAR node’s internal database.What is an Indexer?
A blockchain indexer is an implementation of the push model of getting the data. Instead of actively pulling the data from the source, your helper waits for the data to be sent to it. The data is complete and so the helper can start analyzing it immediately; ideally the data is complete enough to avoid additional pulls to get more details. Getting back to our example, the helper becomes an indexer that receives every Block, along with Chunks, Transactions with its statuses, etc. In the same way the helper analyzes the data and triggers the code to send the user an email with the e-book they bought.
An indexer concept: An indexer listens to the stream of data as it’s being written on chain and can then be immediately filtered and processed to detect interesting events or patterns.
Pull Model vs Push Model
- Pull Model
- Push Model
How it works:
- Your application periodically queries the blockchain
- You request specific data when needed
- You manage the polling frequency
- Simple to implement
- No infrastructure required
- Good for specific queries
- Can miss data between polls
- Inefficient for continuous monitoring
- Limited data availability
- Higher latency
Indexers and “Wide” Queries
The term “wide” queries refers to queries that span multiple blocks.“Wide” queries definition: To query data across many blocks requires the aggregation of results from multiple single-block queries. We can consider these aggregates as coming from “wide” queries.
Indexers in the NEAR ecosystem
NEAR Lake Framework
Simple, reliable indexing in multiple languages (JavaScript, Rust, Python)
Data APIs
Community-built APIs for quick access to on-chain data
When to Use an Indexer
You should consider building an indexer when:Real-time monitoring
You need to monitor blockchain events in real-time and trigger actions based on those events.
Historical data analysis
You need to analyze historical data across multiple blocks or perform complex aggregations.
Custom data structures
You need to transform blockchain data into custom data structures optimized for your use case.
Summary
We hope this article gives you an understanding of the Indexer concept. Also, we hope now you can easily decide whether you need an indexer for your application. The key takeaways:- Blockchains are optimized for writes, not complex queries
- Pull model: You actively query the blockchain
- Push model: Data is streamed to you (indexers)
- Indexers are essential for “wide” queries across multiple blocks
- NEAR Lake Framework is the recommended solution for building custom indexers
Next Steps
Learn how to build your own indexer with NEAR Lake Framework