Resilience

Retries and bulk reads, on by default.

@fastnear/api retries transient RPC failures — HTTP 408/429 and any 5xx, plus JSON-RPC -429/-32000 (except deterministic handler errors like UNKNOWN_ACCOUNT, which fail fast) — with full-jitter exponential backoff, and exposes an explicit bulk read API with a concurrency cap. Both behaviors are on by default and configurable through near.config, so a rate-limited or briefly unhealthy endpoint degrades into slower answers instead of thrown errors.

Tune both knobs

The documented defaults, written out. You only need near.config to change them — omitting this block entirely gives the same behavior.

near.config({
  retry: {
    enabled: true,           // false restores single-attempt behavior
    maxAttempts: 5,          // total attempts including the first
    baseBackoffMs: 250,      // full-jitter exponential backoff bounds
    maxBackoffMs: 30000,
    timeoutMs: 15000,        // per-attempt AbortController timeout (0 disables it)
    respectRetryAfter: true, // honor a Retry-After header, capped at maxBackoffMs
    writePolicy: "transport-only",
  },
  batch: {
    maxConcurrency: 30,      // in-flight cap for near.batch / near.view.many
  },
});
How writes retry
  • writePolicy controls how writes (send_tx / broadcast_tx_*) retry; reads always follow the full retry policy.
  • "transport-only" (the default) retries only pre-response transport and timeout errors, resending identical signed bytes — safe against double-apply.
  • "never" turns write retries off entirely; "all" retries every retryable failure, including after an HTTP response was received.
Bulk reads

Fan out many reads, get settled results back.

NEAR RPC has no array batching, so calls are not merged into one request — near.batch and near.view.many run a concurrency-limited fan-out where each item is its own retried call, at most batch.maxConcurrency (default 30) in flight. Both return settled results in input order: one failing call never rejects the set.

The two entrypoints
  • near.batch(requests) — each { method, params, useArchival?, network? } runs as its own retried call. Write methods are rejected per-item.
  • near.view.many(specs) — the same fan-out for { contractId, methodName, args?, argsBase64?, blockId? } view specs, decoding each ok result like near.view.
Settled results

Check status per item; application failures stay distinguishable from infrastructure ones without re-parsing.

const results = await near.view.many([
  { contractId: "wrap.near", methodName: "ft_balance_of", args: { account_id: "aurora" } },
  { contractId: "wrap.near", methodName: "ft_balance_of", args: { account_id: "intents.near" } },
]);

for (const r of results) {
  if (r.status === "ok") near.print(r.result);
  else if (r.kind === "contract") console.warn("contract reverted:", r.error);
  else console.warn("infra error:", r.kind, r.error);
}
Error kinds
  • "contract" — the contract method reverted or failed: an application failure, not an infrastructure one.
  • "transport" — no HTTP response: network problem or timeout.
  • "http" — a non-2xx HTTP response.
  • "rpc" — a JSON-RPC-level error.
  • "unknown" — a non-RPC failure, e.g. a write method rejected per-item inside near.batch.
  • Thrown errors are FastNearRpcError instances exposing the same kind, plus status, code, data, and retryable.
Go deeper

AI agents: the "Resilience and bulk reads" section of llms-full.txt carries this page in copy-paste form, and recipes.json is the structured catalog behind it. Rate-limited? Free trial credits are available at dashboard.fastnear.com — set near.config({ apiKey }) once you have one.