Batching and Retries
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.
javascript
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://api.mainnet-beta.solana.com", {
method: "POST",
headers: {
"content-type": "application/json",
"x-api-key": process.env.NODE_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
javascript
const wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms))
async function rpc(body, attempt = 0) {
const response = await fetch("https://api.mainnet-beta.solana.com", {
method: "POST",
headers: {
"content-type": "application/json",
"x-api-key": process.env.NODE_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.