One Weird Trick to Save $25,000 On Your RPC Bill
We were re-negotiating our node provider contracts a few weeks ago and found about $25,000 of low-hanging fruit that we managed to cut with a one-line pull request.
eth_chainId
, my old friendThe eth_chainId
RPC call is used to retrieve the unique identifier of the Ethereum blockchain
network the node is connected to. This identifier ensures that transactions are signed and
broadcasted on the correct network, preventing cross-network replay attacks. In decentralized
applications and other web3 integrations, knowing the chain ID is crucial for ensuring compatibility
and security across different blockchain environments.
This matters when you are building something where the chain ID might change. Like if you're building a browser extension or mobile app, it makes a lot of sense to check the chain ID very often.
But in our workloads, we isolate and segregate processes by blockchain network (therefore by chain ID). So the chain ID will never change within a single process.
Most web3 provider libraries will constantly ping to get the node's chain ID. When this happens, the
provider makes the eth_chainId
call.
When you do this once or twice, it doesn't really matter.
When you do it a hundred times, it still doesn't matter.
But when you index everything on every chain, it starts to add up.
How to fix:
Here's one of our configuration files where we get our default web3 provider class:
/**
* Handles things related to our web3 configuration pertaining to this app.
*/
import type { NetworkID } from 'common'
import { Network, Networkish } from 'ethers'
import {
isNullOrUndefined,
RetriableJsonRpcProvider,
} from 'common-node'
import { getNetworkConfig } from './networks.config'
export const getWeb3Provider = (networkId: NetworkID) => {
const netw = getNetworkConfig(networkId)
if (isNullOrUndefined(netw.chainId)) {
throw new Error(Web3 Provider requires a chain ID
)
}
const ethersNetwork: Networkish = Network.from(netw.chainId)
return new RetriableJsonRpcProvider(netw.httpProviderURI[0], ethersNetwork, {
staticNetwork: ethersNetwork,
})
}
Most notably, see how we pass in staticNetwork
into the ethers provider subclass.
It's rare to make such a small code change that saves so much money. After all, as the proverb says:
the best time to save $25,000 on your node provider bill was last year; the second best time is
today in 9df0c717
.
Happy building.