Configure web hosting to keep costs under control
- Vercel and Railway provide convenient serverless platforms for hosting your application, abstracting away the logistics of web hosting relative to using a cloud provider directly. You may end up paying a premium for the convenience, especially at higher volumes.
- AWS and other cloud providers offer more flexibility and commodity pricing.
- Before choosing any service, check pricing and be aware that many providers
offer loss-leader pricing on lower volumes, but then charge higher rates once
you hit a certain threshold.
- For example, suppose there is a $20 plan that includes 1 TB per month of data transfer, with $0.20 per GB beyond that. Do the math to note that the second TB (and onward) will cost $200. If the next tier up says “contact us”, don’t assume the next tier up will be charging $20 per TB.
- If you are building a high-traffic app and you aren’t careful about serving static files more cheaply, it will be easy to exceed the loss-leader tier and pay much more than you expect.
- For production deployments on AWS, consider:
- Amazon S3 + CloudFront for static file hosting and CDN
- AWS Lambda for serverless functions
- Amazon ECS or EKS for containerized applications
- Amazon RDS for database needs
- This setup typically provides granular cost control and scalability for high-traffic applications.
Use a hardcoded value instead of eth_estimateGas call if gas usage is static
Many on-chain actions have a fixed gas cost. The simplest example is that a
transfer of native tokens always costs 21,000 gas, but there are many others.
This makes it unnecessary to call eth_estimateGas for each transaction.
Use a hardcoded value instead, as suggested
here.
Eliminating an eth_estimateGas call substantially speeds up the user workflow
in the wallet, and avoids a potential bad behavior in some wallets when
eth_estimateGas reverts (discussed in the linked page).
Reduce eth_call latency by submitting multiple requests concurrently
Making multiple eth_call requests serially will introduce unnecessary latency
due to multiple round trips to an RPC node. You can make many eth_calls
concurrently, either by condensing them into a single eth_call or by
submitting a batch of calls. Alternatively, you might find it better to switch
to an indexer.
Condensing multiple eth_calls into one
- Multicall: Multicall is a utility smart contract that allows you to
aggregate multiple read requests (
eth_call) into a single one. This is particularly effective for fetching data points like token balances, allowances, or contract parameters simultaneously. The standardMulticall3contract is deployed at0xcA11bde05977b3631167028862bE2a173976CA11on both Monad Mainnet and Monad Testnet. Many libraries offer helper functions to simplify multicall usage, e.g. viem. Read more aboutMulticall3here. - Custom Batching Contracts: For complex read patterns or scenarios not
easily handled by the standard multicall contract, you can deploy a custom
smart contract that aggregates the required data in a single function, which
can then be invoked via a single
eth_call.
Multicall executes calls serially as you can see from the code
here.
So while using multicall avoids multiple round trips to an RPC server, it is
still inadvisable to put too many expensive calls into one multicall. A batch
of calls (explained next) can be executed on the RPC in parallel.
Submitting a batch of calls
Most major libraries support batching multiple RPC requests into a single message. For example,viem handles Promise.all() on an array of promises by
submitting them as a single batch:
Use indexers for read-heavy loads
If your application frequently queries historical events or derived state, consider using an indexer, as described next.Use an indexer instead of repeatedly calling eth_getLogs to listen for your events
Below is a quickstart guide for the most popular data indexing solutions. Please
view the indexer docs for more details.
Using Allium
- Allium Explorer
- Blockchain analytics platform that provides SQL-based access to historical blockchain data (blocks, transactions, logs, traces, and contracts).
- You can create Explorer APIs through the
GUI to query and analyze historical
blockchain data. When creating a Query for an API
here (using the
Newbutton), selectMonad MainnetorMonad Testnetfrom the chain list. - Relevant docs:
- Allium Datastreams
- Provides real-time blockchain data streams (including blocks, transactions, logs, traces, contracts, and balance snapshots) through Kafka, Pub/Sub, and Amazon SNS.
- GUI to create new streams
for onchain data. When creating a stream, select the relevant
Monad MainnetorMonad Testnettopics from theSelect topicsdropdown. - Relevant docs:
- Allium Developers
- Enables fetching wallet transaction activity and tracking balances (native, ERC20, ERC721, ERC1155).
- For the request’s body, use
monad_mainnetfor Monad Mainnet ormonad_testnetfor Monad Testnet as thechainparameter. - Relevant docs:
Using Envio HyperIndex
- Follow the quick start
to create an indexer. In the
config.yamlfile, use network ID10143to select Monad testnet (used in the example below) or network ID143for Monad mainnet. - Example configuration
-
Sample
config.yamlfileconfig.yaml -
Sample
EventHandlers.tsEventHandlers.ts
-
Sample
- Important: The
rpc_configsection under a network (checkconfig.yamlsample) is optional and should only be configured if you experience issues with the default Envio setup. This configuration allows you to:- Use your own RPC endpoint
- Configure block fetching parameters for better performance
- Relevant docs:
Using GhostGraph
See also: Ghost
- Relevant docs:
Using Goldsky
See also: Goldsky
- Goldsky Subgraphs
- To deploy a Goldsky subgraph follow this guide.
- As the network identifier, use
monad-mainnetfor Monad Mainnet ormonad-testnetfor Monad Testnet. For subgraph configuration examples, refer to The Graph Protocol section below. - For information about querying Goldsky subgraphs, see the GraphQL API documentation.
- Goldsky Mirror
- Enables direct streaming of on-chain data to your database.
- For the chain name in the
dataset_namefield when creating asourcefor a pipeline, usemonad_mainnetfor Monad Mainnet ormonad_testnetfor Monad Testnet (check below example) - Example
pipeline.yamlconfig filepipeline.yaml - Relevant docs:
Using QuickNode Streams
See also: QuickNode Streams
- On your QuickNode Dashboard, select
Streams>Create Stream. In the create stream UI, select Monad Mainnet or Monad Testnet under Network. Alternatively, you can use the Streams REST API to create and manage streams—usemonad-mainnetfor Monad Mainnet ormonad-testnetfor Monad Testnet as the network identifier. - You can consume a Stream by choosing a destination during stream creation. Supported destinations include Webhooks, S3 buckets, and PostgreSQL databases. Learn more here.
- Relevant docs:
Using The Graph’s Subgraph
See also: The Graph
- Network ID: Use
monad-mainnetfor Monad Mainnet ormonad-testnetfor Monad Testnet - Example configuration
-
Sample
subgraph.yamlfilesubgraph.yaml -
Sample
mappings.tsfilemappings.ts -
Sample
schema.graphqlfileschema.graphql
-
Sample
- Relevant docs:
Using thirdweb’s Insight API
See also: thirdweb
- REST API offering a wide range of on-chain data, including events, blocks, transactions, token data (such as transfer transactions, balances, and token prices), contract details, and more.
- Use chain ID
143for Monad Mainnet or10143for Monad Testnet when constructing request URLs. - Relevant docs:
Manage nonces locally if sending multiple transactions in quick succession
This only applies if you are setting nonces manually. If you are delegating
this to the wallet, no need to worry about this.
eth_getTransactionCountrequires a network request. If you have multiple transactions from the same wallet in short succession, you should implement local nonce tracking.

