Rate limits & quotas
Rate limits & quotas
Per-key throughput tiers, daily/monthly quotas, and per-IP ceilings — every number generated from config, with self-describing headers and a fail-open posture.
Drazill enforces limits at two levels: a per-key tier (throughput + quota) and a per-IP ceiling (a coarse shared-address guard that runs before authentication). Every table here is generated from the enforcing code/config and drift-gated — the numbers cannot rot.
Per-key throughput (tier)
Each API key has a rate-limit tier with a requests-per-minute ceiling. Tier changes are
admin-reviewed (self-serve requests via POST /api/v1/api-keys/{id}/tier-request).
Daily & monthly quotas
On top of the per-minute ceiling, keys carry daily and monthly request quotas (part of the
Data & API usage layer). Usage is metered when DATA_API_USAGE_METERING_ENABLED is on.
Metering fails open. If the usage store (Redis) has a blip, metering and quota
enforcement fail open — a cache outage never denies a paying customer a request. The
per-minute tier ceiling still applies. This is a deliberate customer-favourable posture
(app/core/config.py).
Per-IP ceilings
Before a request is authenticated, a per-IP limiter applies a coarse ceiling by path category. These are per-IP, not per-user — many legitimate users share an address behind carrier-grade NAT, corporate proxies, and VPNs, so the ceilings are generous. Fine-grained throttling is the per-key tier above.
The per-IP limiter also fails open if its store is unavailable — a blip must never block signup or trading.
Response headers
Limits are self-describing — you don’t have to guess:
These are exposed via CORS so a first-party browser client can read them
(docs/api/cors-and-auth.md).
Handling 429
On a 429, back off for the Retry-After duration and retry. The SDKs do this for you —
configure the retry budget and they retry 5xx and 429 responses, honouring Retry-After:
If you handle HTTP directly, read Retry-After and sleep before retrying; use an
Idempotency-Key on any mutation you retry
so a retry can never double-apply.
The full, per-plan rate/quota sheet is maintained in the repo at
docs/legal/api-rate-plans.md — which carries a PENDING LEGAL REVIEW banner: the
numbers there (and here) are the technical enforcement values from app/core/config.py
and app/models/api_key.py, not a price sheet or a service-level guarantee. Pricing
and contractual commitments are owner-defined and pending counsel review.

