Rate limiting
Schematic rate-limits API requests per account. Every API key in an environment draws from the same budgets, and each budget allows a sustained rate of requests per second plus a burst allowance above it. You can send a short burst up to the burst size, then continue at the sustained rate.
A request is checked against every limit that applies to it. A write, for example, counts against both the global limit and the mutation limit. If any one of them is exhausted, the request is rejected with a 429.
Limits
Flag checks are reads that happen to use POST, so they count only against the global limit. Event submission counts against the events-ingest limit instead of the mutation limit.
Environments
The global and mutation limits are tracked separately for production and non-production environments. Your production environment has its own budget; development and staging environments share a second budget with the same numbers. Load testing in staging cannot starve production, and adding more non-production environments does not add capacity.
The events-ingest and analytics limits are account-wide: one budget covers every environment.
Per-key caps
You can cap an individual API key at a percentage of your account’s limits. The cap applies to every limit above: a key capped at 25% gets 25% of the global, mutation, events-ingest, and analytics budgets, rate and burst alike. A cap only lowers a key’s share; it never grants budget beyond the account’s.
A key under its cap consumes the account budget as usual. A key over its cap is rejected with a 429 and consumes none of the account budget, so a capped key can take at most its share from the keys that share the account. Give a scanner, backfill, or batch-job key a small cap so it cannot starve the keys serving production traffic.
The 429 body names the limit the key exceeded (mutation, for example), and the X-RateLimit-* headers describe the key’s own capped limit rather than the account’s.
To set a cap in the dashboard, open the API key’s create or edit dialog, turn on Limit throughput, and enter a percentage from 1 to 99. Through the API, pass rate_limit_percent when you create or update a key:
API key responses include rate_limit_percent, which is null for an uncapped key.
Response headers
Every response from a rate-limited endpoint carries three headers describing the tightest limit the request was subject to:
These headers are present on successful responses too, so you can watch X-RateLimit-Remaining and slow down before you are rejected. They are exposed to browsers through CORS.
When a request is rejected, the response is a 429 Too Many Requests with a Retry-After header (in seconds) and a body naming the limit you hit:
The bucket value is one of global, mutation, events_ingest, or analytics.
Handling limits
- Honor
Retry-After. When you receive a429, wait at least that many seconds before retrying. For retries beyond the first, back off exponentially and add jitter so that many workers do not retry in lockstep. - Batch events. Send events through
POST /event-batchinstead of one request per event. One batch request counts once against the events-ingest limit regardless of how many events it carries. - Cache flag checks. Use the SDKs, which cache flag values locally and refresh them in the background, rather than calling the API on every evaluation. Use the bulk flag-check endpoint when you need many flags at once.
- Pace analytics reads.
GET /eventsand the feature-usage endpoints scan history and have the lowest limit. Fetch them on a schedule rather than on demand, and page through results with a delay between requests. - Watch for fan-out. Limits are per account, not per worker or per API key. A job that runs on many machines in parallel shares one budget; coordinate or throttle it centrally.
- Spread out bulk updates. A nightly job that upserts every company or user at once will exhaust the mutation limit. Spread the work over a longer window, or send trait updates as identify events instead.
Schematic’s SDKs handle most of this for you. The server-side SDKs cache flag checks and queue events; the front-end SDKs cache flag values, batch checks, and keep values fresh over a WebSocket connection.
Need a higher limit?
If your workload needs more than the limits above, contact support and describe the use case. Limits can be raised per account.