Best practices
Fewer requests, fewer surprises: batch, retry politely, page through logs and keep your tokens safe.
Contents
Batch independent calls
Up to 100 calls in one request. Fewer round trips, the same credits.
- viem:
http(url, { batch: { batchSize: 100 } })(viem’s default batch is larger than 100 calls). ethers v6 batches calls made within a few milliseconds of each other by default (batchStallTime), up to 100 per batch. web3.py:w3.batch_requests(). - Each call counts against your requests per second, so very large batches can still answer
rate_limited. - Results come back in the order you sent them, with your ids. One failing call does not fail the batch.
Retry 429 and 503 with backoff
Honour Retry-After when it is there; otherwise wait 0.5 s, 1 s, 2 s and so on, with a little random jitter.
// Retry 429 and 503 with Retry-After or exponential backoff (at most 5 tries).
async function rpc(body, tries = 5) {
for (let i = 0; ; i++) {
const res = await fetch(`https://rpc.blockmetric.io/eth/${process.env.BLOCKMETRIC_RPC_TOKEN}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(body),
})
if ((res.status !== 429 && res.status !== 503) || i === tries - 1) return res.json()
const wait = Number(res.headers.get('Retry-After')) * 1000 || Math.min(30_000, 500 * 2 ** i)
await new Promise((r) => setTimeout(r, wait + Math.random() * 250))
}
}Do not retry 4xx errors other than 429: they mean the request itself is wrong (error codes). Never retry eth_sendRawTransaction blindly; check the transaction hash first.
Page through eth_getLogs
One call covers at most 10,000 blocks (HyperEVM 50). Narrow by address and topics; step through long ranges.
import { createPublicClient, http, parseAbiItem } from 'viem'
import { mainnet } from 'viem/chains'
const client = createPublicClient({ chain: mainnet, transport: http(`https://rpc.blockmetric.io/eth/${process.env.BLOCKMETRIC_RPC_TOKEN}`) })
const transfer = parseAbiItem('event Transfer(address indexed from, address indexed to, uint256 value)')
// Page through a long range in steps the chain allows (10,000 blocks; HyperEVM 50).
const STEP = 10_000n
for (let from = 19_000_000n; from <= 19_100_000n; from += STEP) {
const logs = await client.getLogs({ address: '0x0000000000000000000000000000000000000000', event: transfer, fromBlock: from, toBlock: from + STEP - 1n })
console.log(from, logs.length)
}Keep tokens safe
- One token per app and environment (production, staging, a script). You see usage per token and can revoke one without touching the others.
- Browser apps: a token in front-end code is public. Set allowed origins on the token, so other sites cannot use it.
- Servers: set an IP allowlist and keep the token in an environment variable such as
BLOCKMETRIC_RPC_TOKEN. - Never commit a token to a public repository. If one leaked, rotate it on your dashboard: the old token stops working within a minute.
- Never put an API key in a URL. Only RPC endpoint tokens (
bmr_…) belong in an RPC URL.
Cache what does not change
- Blocks, receipts and transactions deep below the head do not change: keep them on your side instead of asking again.
eth_chainIdandnet_versionare free, but a fixed chain id in your client (ethersstaticNetwork, a viem chain) saves the round trip.- Poll
eth_blockNumberat most once per block time, or subscribe tonewHeadsover WebSocket instead of polling. - Your requests on one chain stay on the same node for 30 seconds, so "latest" does not jump back between two nodes.
Watch your usage
- Every answer on a Global plan carries
X-Blockmetric-CreditsandX-Blockmetric-Credits-Remaining(dedicated throughput has no credits). - Your dashboard shows credits per chain and day, recent errors and the latency our gateway measured for your requests.
- We e-mail you at 80 % and 100 % of your monthly credits. Overage is optional and always capped by you.
Code snippets in these docs are licensed under MIT-0: copy them into your own code without attribution. Use of Blockmetric RPC is governed by the terms. Independent infrastructure, not affiliated with the chains or their foundations.