RPC Batching and Retries
Reduce RPC calls and retry temporary failures without duplicate work.
Batch independent reads. Retry only temporary failures.
Send a batch
A JSON-RPC batch is an array of request objects. Give each request a unique ID.
const requests = [ { jsonrpc: "2.0", id: "slot", method: "getSlot", params: [{ commitment: "confirmed" }], }, { jsonrpc: "2.0", id: "health", method: "getHealth", }, { jsonrpc: "2.0", id: "epoch", method: "getEpochInfo", params: [{ commitment: "confirmed" }], },] const response = await fetch("https://rpc.nln.clr3.org", { method: "POST", headers: { "content-type": "application/json", "x-api-key": process.env.NLN_API_KEY, }, body: JSON.stringify(requests),}) const results = await response.json()const byId = Object.fromEntries(results.map((item) => [item.id, item]))console.log(byId.slot.result)Response order does not need to match request order. Match each result by ID.
Pick retryable failures
Retry these responses:
- HTTP
429 - HTTP
500 - HTTP
502 - HTTP
503 - HTTP
504 - Network timeout
- Connection reset before a response
Do not retry these responses without changing the request:
- HTTP
400 - HTTP
401 - JSON-RPC
-32601 - JSON-RPC
-32602
Use bounded backoff
const wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms)) async function rpc(body, attempt = 0) { const response = await fetch("https://rpc.nln.clr3.org", { method: "POST", headers: { "content-type": "application/json", "x-api-key": process.env.NLN_API_KEY, }, body: JSON.stringify(body), signal: AbortSignal.timeout(10_000), }) if ([429, 500, 502, 503, 504].includes(response.status) && attempt < 4) { const base = 250 * 2 ** attempt const jitter = Math.floor(Math.random() * 150) await wait(base + jitter) return rpc(body, attempt + 1) } const result = await response.json() if (!response.ok || result.error) { throw new Error(result.error?.message ?? `HTTP ${response.status}`) } return result.result}Protect transaction submission
Treat sendTransaction differently from reads.
- Keep the same signed transaction across retries.
- Query the signature before a second submission.
- Stop after the blockhash expires.
- Do not build a new transaction inside the retry loop.