Operation
Batching

Batch requests

AIOpen as plain markdown for AI

eRPC handles JSON-RPC batching at two independent layers: it accepts batch arrays from clients, and it can group outbound calls into batches toward upstreams that support it. The two layers compose — a single-request client still benefits from upstream batching, and a batch-sending client still gets per-request caching and deduplication.

👋

For EVM workloads, batching is often an anti-pattern (opens in a new tab). The whole batch is as slow as its slowest request, partial failures are harder to handle (HTTP status is always 200), and many providers charge per method call regardless. When eRPC is co-located with your services the overhead of individual requests is negligible — prefer that path.

You can configure:

  • Outgoing batchingjsonRpc.supportsBatch, batchMaxSize, batchMaxWait per upstream
  • Incoming batching — always accepted; no config needed; works on both chain-scoped and project-scoped URLs
  • Multi-chain batches — embed networkId in each item and send to the project root URL

Outgoing batch config

Tell eRPC to accumulate requests and forward them as a batch to a specific upstream.

projectsupstreams[]jsonRpc
erpc.yaml
projects:  - id: main    upstreams:      - id: blastapi-chain-42161        endpoint: https://arbitrum-one.blastapi.io/xxxxxx        jsonRpc:          # Accumulate requests and forward as a JSON-RPC batch array.          supportsBatch: true          # Max time to wait before flushing a partial batch.          batchMaxWait: 100ms          # Max requests per batch (provider-enforced limit).          batchMaxSize: 100

For certain well-known providers (Alchemy, Infura, etc.) batching is enabled by default.

Incoming batch examples

Single-chain batch

Send a JSON array to the chain-scoped URL. Each item must include id, jsonrpc, method, and params.

curl --location 'http://localhost:4000/main/evm/1' \
  --header 'Content-Type: application/json' \
  --data '[
    {
      "method": "eth_getBlockByNumber",
      "params": ["0x1203318888888888", false],
      "id": 8888,
      "jsonrpc": "2.0"
    },
    {
      "method": "eth_getBlockByNumber",
      "params": ["0x1203319", false],
      "id": 9999,
      "jsonrpc": "2.0"
    }
  ]'

Multi-chain batch

Add networkId to each item and send to the project root URL.

curl --location 'http://localhost:4000/main' \
  --header 'Content-Type: application/json' \
  --data '[
    {
      "networkId": "evm:1",
      "method": "eth_getBlockByNumber",
      "params": ["0x1203888", false],
      "id": 888,
      "jsonrpc": "2.0"
    },
    {
      "networkId": "evm:42161",
      "method": "eth_getBlockByNumber",
      "params": ["0x1203999", false],
      "id": 999,
      "jsonrpc": "2.0"
    }
  ]'
Copy for your AI assistant — full batching referenceExpand for every option, default, and edge case — or copy this entire section into your AI assistant.

Incoming batch (client to eRPC)

A client can POST a JSON array of JSON-RPC objects to any eRPC endpoint. eRPC explodes it into individual requests, routes each one through the normal pipeline (selection policy, failsafe, cache, rate limits), then reassembles the responses in the original order before replying.

The response is always a JSON array with the same length as the request. HTTP status is always 200 OK even when individual items errored — inspect each item's error field.

Each item must carry a unique id field so eRPC can correlate responses. Items without id (notifications) are accepted but produce no response entry.

For multi-chain batches, add networkId: "evm:<chainId>" to each item and POST to the project root URL (/<projectId>). Single-chain batches go to the chain URL (/<projectId>/evm/<chainId>).

Outgoing batch (eRPC to upstream)

Controlled per-upstream via jsonRpc:

FieldTypeDefaultDescription
supportsBatchboolfalse (auto-true for known providers)Enable outgoing batching for this upstream.
batchMaxSizeint100Maximum requests per batch. Enforced before flushing.
batchMaxWaitduration0 (flush immediately)How long to accumulate requests before flushing.

When supportsBatch: true, eRPC collects requests destined for the same upstream within the batchMaxWait window and sends them as a single HTTP request carrying a JSON array. If the batch hits batchMaxSize before the window expires it flushes immediately.

Outgoing batching is transparent to clients — it applies even to clients that send individual requests.

Interaction with the multiplexer (deduplication)

eRPC's multiplexer deduplicates in-flight requests by (network, method, params) before batching. If two clients send the same call concurrently, only one upstream request is made and both clients receive the same response. Deduplication happens before the outgoing batch is assembled, so it reduces batch size and upstream cost.

Interaction with cache

Cache lookups happen per-request before batching. A request that hits the cache is never forwarded upstream, whether the client sent it alone or inside a batch. A partial batch where some items are cached and some are not will only forward the cache-miss items to the upstream.

Per-request directives inside a batch

HTTP request headers (e.g. X-ERPC-Skip-Cache-Read, X-ERPC-Retry-Count) apply to the whole HTTP call. When a client sends a batch, the same headers apply to every item in that batch. There is no per-item header mechanism in JSON-RPC.

Response shape and ordering

eRPC preserves the original ordering of a batch response. If the upstream returns items in a different order (by id), eRPC reorders them to match the client's request array position before replying.

Common pitfalls

  • batchMaxWait latency tradeoff — a non-zero wait adds guaranteed latency for every request. It is only worth setting when your upstream charges per HTTP request (not per method call) and you send many concurrent calls. For providers that charge per method call it saves nothing.
  • Mixed-method batches — eRPC may route different items to different upstreams (e.g. based on method filters or circuit-breaker state). A batch to a client is assembled from responses that may have come from multiple upstreams.
  • Error semantics — a batch item that fails returns {"id": ..., "error": {...}} in the array. The HTTP response is still 200. Clients must inspect each item individually.
  • gzip interaction — if the upstream returns a gzip-compressed batch response, eRPC decompresses before exploding into individual items. The client-facing response is always uncompressed unless the client explicitly requested Accept-Encoding: gzip and eRPC is configured to forward it.
  • Rate limits apply per request, not per batch — a 100-item batch consumes 100 units of the upstream's rate-limit budget.
  • batchMaxSize is a flush trigger, not a hard cap — if batchMaxWait expires first, the batch may be smaller. Upstreams that enforce a strict cap may reject oversized batches with a top-level error; set batchMaxSize to match the provider's documented limit.

Append .llms.txt to this URL (or use the AI link above) to fetch the entire expanded reference as plain markdown for an AI assistant.