Handle JSON-RPC batches with independent outcomes

Match responses by id and retry only the requests whose result is unresolved.

A batch is a container

JSON-RPC 2.0 permits an array of requests. The server may process requests in any order and return responses in any order. A batch does not promise an atomic blockchain snapshot, sequential execution or one shared success state. Provider size and accounting limits are separate from the protocol.

Match by identifier

[{"jsonrpc":"2.0","id":"height","method":"eth_blockNumber","params":[]},{"jsonrpc":"2.0","id":"chain","method":"eth_chainId","params":[]}]

# Valid response ordering:
[{"jsonrpc":"2.0","id":"chain","result":"0x1237"},{"jsonrpc":"2.0","id":"height","result":"0x100"}]

Use unique ids within the batch. Build a map keyed by id and validate every expected response. Do not zip request and response arrays by position.

Keep failures local

  1. Check the HTTP result and parse the body without discarding JSON-RPC error objects.
  2. Classify each id as result, explicit error or missing response.
  3. Retry retryable read failures with backoff. Reduce batch size when payload or time limits are implicated.
  4. For a state-changing submission with an uncertain transport outcome, reconcile its transaction hash before initiating a different operation.

Make the batch operationally useful

Bound batches by response bytes and method cost as well as number of calls. Ten expensive historical traces can be heavier than hundreds of simple reads. Keep per-method metrics and use explicit block references when consistency matters. Requests without ids are notifications and have no response, so avoid them for operations whose success your application needs to verify.

Sources

Continue reading