Skip to content

Limits

Every limit the API enforces, in one place. If you are sizing a backfill script, skip to sizing an import.

Counted in fixed one-minute windows, per tenant. A rejected request returns 429 with code RATE_LIMITED and a Retry-After header in seconds — respect it rather than retrying immediately.

Window Limit Applies to
Tenant 10,000 requests/min every authenticated request — user tokens and server tokens together
Batch 600 requests/min /v1/batch/* only, on its own window
Auth failures 20 failures/min per IP requests that fail authentication

The batch window is separate on purpose: a running import cannot starve your app’s normal traffic, and a traffic spike cannot stall your import. Batch calls do not also charge the tenant window.

Only genuine auth failures count against the IP limit — a 429 or an internal error does not. That limit exists to make credential-guessing expensive, so it is per IP rather than per tenant.

Cap Value
Items per batch call 100 (/v1/batch/users, /follows, /activities)
Page size (limit) 100 max, 20 default
User token TTL 24h max, 1h default
Live promoted activities per tenant 100 — an abuse guard, not a plan limit; retracted rows do not count
Promoted rows per feed sidecar 10, newest first
refs per activity 4 — objects one activity points at
Feed refs per promoted audience 20, matched with OR — a different thing: the feeds a promoted activity targets, not objects

Keep user tokens short. The 24h ceiling is an upper bound, not a recommendation — mint them per session, and use revokeUserTokens when a user logs out or is banned.

The batch window is the binding constraint, and it is generous: 600 calls/min × 100 items = 60,000 items per minute. In practice you will hit your own database read speed first.

Concretely, for a backfill of N items:

calls = ceil(N / 100)
minutes = calls / 600

50,000 follow edges is 500 calls — under a minute of wall clock at the limit, and comfortably inside it at any sane concurrency. A few thousand users’ worth of history does not come close.

Two rules that matter more than the arithmetic:

  • Serial is usually fine. Concurrency above ~10 in-flight calls buys little and makes a 429 more likely. Start serial, measure, then raise it.
  • Handle 429 by sleeping Retry-After, not by retrying in a tight loop. A batch call is safe to replay when activities carry foreign_id + time (see Idempotency).

There is no cap on the number of users, feeds, follow edges, or activities in a tenant, and no per-feed follower ceiling. Fan-out to a very large follower count is chunked and streamed rather than refused.