Skip to content

Quotas and rate limits

Two kinds of limits apply:

  • Daily quotas cap the requests and the response bytes per UTC day. They reset at 00:00 UTC.
  • Rate limits cap requests per second and, on the free tier, concurrent calls.
Plan Counted per Quota per UTC day When it runs out
Free Client IP, and site (the host in Referer) 128k requests or 2 GB, whichever comes first 403, more requests dropped at random as usage nears the quota
Boost Endpoint: all its tokens, sites and IPs together 256k requests and 4 GB; reaching either one is enough 429 with a JSON body until 00:00 UTC
Unlimited – No daily quota –
Enterprise – No daily quota –
  • Every request counts, including errors and rejected requests. Bytes are the size of the responses.
  • Usage reaches the edges with a delay of a few minutes, so a busy client can go a little over its quota before it is stopped.
  • On the free tier, IPFS gateway traffic counts toward the same quota as the APIs.

As a client IP or a site gets close to its daily quota, the edge rejects a growing share of its requests at random. Once the quota is used up, it rejects them all until 00:00 UTC. Rejected requests get:

HTTP/2 403
Daily free API quota exceeded

Follow free-tier usage on the public dashboard. If your app needs a higher request rate, its own API token or analytics, the Boost plan gives an endpoint 256k requests and 4 GB a day that no one else shares. More can be added in blocks of 256k requests and 4 GB a day; steady traffic beyond that suits Unlimited.

From 80 % of either quota, responses carry an X-And-Quota header and the portal sends you an email. At 100 % of either quota, the edge answers every request of the endpoint with a 429 until 00:00 UTC, and the portal emails you again:

HTTP/2 429
content-type: application/json
retry-after: 20117
x-and-quota: block=1;reqs=256154;bytes=3200000000;ts=2026-11-02
{"message":"Daily Boost quota exceeded","ld":"acme","requests":256154,"bytes":3200000000,"day":"2026-11-02","reset_in":20117}
Field Meaning
message Always “Daily Boost quota exceeded”
ld Your endpoint’s log name, as shown in the portal analytics
requests, bytes The endpoint’s usage today
day The UTC day the quota is counted for
reset_in Seconds until 00:00 UTC, the same as Retry-After

X-And-Quota has the form block=<0|1>;reqs=<requests today>;bytes=<bytes today>;ts=<UTC day>. block=0 is the warning from 80 %; block=1 means the quota is used up.

Retrying before 00:00 UTC does not help. On the Billing page of the portal an organization admin can add Extra 256k requests and 4 GB a day blocks ($32 / month each, up to 7, an overage that raises both daily quotas) or upgrade to Unlimited, which drops the quota. Either takes effect within a few minutes.

No daily quota. On Unlimited the rate limits below still apply; Enterprise has no API rate limits.

Plan Limits
Free 30 req/s, 10 concurrent calls and 18 transaction POSTs per second per client IP; bot traffic (no browser Referer or Origin) 5 req/s per IP; 1000 req/s per site
Boost 120 req/s per client IP, split across the region's edges
Unlimited 600 req/s per client IP, split across the region's edges
Enterprise No API rate limit (Unlimited’s features otherwise); the IPFS gateway limit below still applies
IPFS gateway 100 req/s per IP for Algorand mainnet assets, 10 req/s for other content

Over a rate limit, the edge answers at once with a plain 429, without the JSON body. Wait and retry with exponential backoff.

On Free and Boost the edges add 50 ms or more to backend and bot requests: those without a browser Referer. Browser apps and msgpack requests (?format=msgp) get none. Unlimited and Enterprise get none at all.

A 429 with a JSON body whose message is “Daily Boost quota exceeded” means the daily quota is used up: stop until 00:00 UTC. Any other 429 is a rate limit: back off and retry. In browsers, read the body rather than the headers: cross-origin scripts may not be allowed to read Retry-After or X-And-Quota.

async function callNodely(url, init = {}, attempt = 0) {
const res = await fetch(url, init);
if (res.status !== 429) return res;
if (res.headers.get("content-type")?.includes("application/json")) {
const body = await res.clone().json().catch(() => null);
if (body?.message === "Daily Boost quota exceeded") return res; // wait for 00:00 UTC
}
if (attempt >= 5) return res;
// Rate limit: exponential backoff with jitter.
await new Promise((resolve) => setTimeout(resolve, 250 * 2 ** attempt + Math.random() * 250));
return callNodely(url, init, attempt + 1);
}
  • Cache what does not change. Blocks and confirmed transactions are immutable: fetch them once.
  • Ask for new data only, for example with min-round on indexer searches, instead of polling from round 0 or 1.
  • Reuse connections with HTTP/2 or keep-alive: see API speedup.
  • Limit concurrency: on the free tier, no more than 10 calls at once, 2 for blocks and 1 for a paginating request (next=).
  • Do not send the same request from many servers in the same round.

The full free-tier rules are in the fair usage policy.