Limits and retention
This page covers everything that bounds your traffic and your data on Gate: per-key and org-level rate limits, rolling usage caps on cost, tokens, and requests, the maximum request size, and how long Gate retains your logs, metrics, and audit records.
How rate limiting works
Every request to the gateway passes through two checks, in this order:
- Org-level rate limit. A requests-per-minute cap shared across every API key in your organization. Configured by your org admin in the dashboard or via the API.
- Per-key rate limit. An optional cap on a single API key. Useful for sandboxing CI pipelines, shared team keys, or untrusted clients.
Both layers use a sliding window of 60 seconds. Counters are maintained per key or per org, and they do not stack. If both are configured, the org-level limit is checked first. A rejection at either layer returns HTTP 429.
Note: In multi-replica deployments, rate limit counters are shared across all gateway replicas via a distributed store. Single-replica setups use an in-process store that is accurate but does not survive pod restarts.
Rate limit response headers
All gateway responses include rate limit headers so your client can track headroom without waiting for a rejection. The exact headers present depend on which limit applied.
Per-key headers
Per-key limits set X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset. No X-RateLimit-Scope header is emitted for per-key limits.
X-RateLimit-Limit: 600X-RateLimit-Remaining: 487X-RateLimit-Reset: 1749254400Org-level headers
When an org-level limit is configured, two extra headers are always set (even when the per-key limit is also active):
X-RateLimit-Limit: 1000X-RateLimit-Remaining: 823X-RateLimit-Reset: 1749254400X-RateLimit-Scope: orgX-RateLimit-Org-Limit: 1000X-RateLimit-Org-Remaining: 823| Header | Description |
|---|---|
X-RateLimit-Limit | The cap that applies to this request. |
X-RateLimit-Remaining | Requests remaining before the active limit fires. |
X-RateLimit-Reset | Unix timestamp (seconds) when the current window resets. |
X-RateLimit-Scope | org or passthrough-ip. Only present on org-level and passthrough-IP rejections; not emitted for per-key limits. |
X-RateLimit-Org-Limit | (org limit only) The org-wide cap. |
X-RateLimit-Org-Remaining | (org limit only) Org-wide remaining. Always present when the org limit is configured, whether or not it fired. |
HTTP 429 response body
When any rate limit is exceeded the gateway returns HTTP 429 with an error body of the form:
{ "error": { "code": "rate_limit_exceeded", "message": "Rate limit exceeded. Please retry after the reset window.", "source": "gateway", "retryAfter": 1749254400 }}For org-level rejections the message is:
{ "error": { "code": "rate_limit_exceeded", "message": "Organization rate limit exceeded. Please retry after the reset window.", "source": "gateway", "retryAfter": 1749254400 }}| Field | Description |
|---|---|
code | Always rate_limit_exceeded for rate limit rejections. |
source | Always gateway. The request is stopped by Gate before the upstream is called. |
retryAfter | Unix timestamp (seconds) when you may safely retry. |
The x-gate-error-source: gateway response header carries the same source value for clients that inspect headers.
Tip. Use
retryAfterdirectly instead of sleeping for a fixed interval. The value is the exact window reset time, so you avoid both over-sleeping and premature retries.
Configuring rate limits
Per-key rate limit
Set rateLimit when creating or updating an API key via the keys API:
POST /api/v1/gateway/api-keysAuthorization: Bearer $GATE_API_KEYContent-Type: application/json
{ "name": "CI pipeline key", "orgId": "org_…", "rateLimit": 60}rateLimit is requests per minute. Set it to null (or omit it) to remove the cap. The field is also editable via PATCH /api/v1/gateway/api-keys/:id.
Org-level rate limit
Org-level limits are set by an admin in the dashboard under Settings, Rate limits. The gatewayRateLimit field on the org’s entitlements row is the source of truth. null means no org cap is applied.
Usage limits (rolling spend/token/request caps)
In addition to per-minute rate limits, paid-plan organizations can create usage limits, soft ceilings on cost, token consumption, or request count over a rolling time window (1 hour, 1 day, 1 week, or 1 month). These are separate from the sliding-window rate limiter and are checked after rate limiting, before the upstream call.
Usage limits are managed via the keys API at /api/v1/gateway/usage-limits.
Note: Usage limits require a paid plan. Attempting to create or update a limit on a free-plan org returns
403.
Create a usage limit
POST /api/v1/gateway/usage-limitsAuthorization: Bearer $GATE_API_KEYContent-Type: application/json
{ "orgId": "org_…", "name": "Daily token ceiling", "limitType": "tokens", "threshold": "5000000", "timeWindow": "1 day"}| Field | Required | Description |
|---|---|---|
orgId | Yes | Organization to apply the limit to. |
name | Yes | Human-readable label shown in the dashboard. |
limitType | Yes | cost (USD), tokens (total tokens), or requests (request count). |
threshold | Yes | Numeric string. For cost, this is USD (e.g. "25.00"). For tokens or requests, a whole number. |
timeWindow | Yes | "1 hour", "1 day", "1 week", or "1 month". |
apiKeyId | No | Scope the limit to a single key. Omit (or pass null) for an org-wide limit. |
enabled | No | true (default) or false. Disabled limits are stored but not checked. |
Update or delete
PATCH /api/v1/gateway/usage-limits/:idDELETE /api/v1/gateway/usage-limits/:idPATCH accepts the same optional fields as POST (all fields are optional on update). DELETE removes the limit permanently. It does not affect historical usage data.
Inspect current usage
GET /api/v1/gateway/usage-limits/:id/usageReturns the current rolling usage and whether the threshold has been reached:
{ "data": { "limitId": "lim_…", "limitType": "tokens", "threshold": "5000000", "currentUsage": "3812044", "timeWindow": "1 day", "exceeded": false }}Request size
| Service | Limit |
|---|---|
| Gateway proxy (LLM requests) | 25 MB per request body |
| Dashboard API (configuration calls) | 10 MB per request body |
The 25 MB gateway limit matches Anthropic’s published request ceiling. Long agentic conversations that accumulate large tool-result blobs can approach it. Exceed it and the gateway returns HTTP 413 with code request_too_large.
Data retention
Every request is recorded, but the different kinds of data Gate keeps have different lifetimes, and two of them depend on your plan.
| Data | Free | Pro |
|---|---|---|
| Logs: request and response bodies, turn content, security-decision payloads | 30 days | 90 days |
| Metrics: activity, cost, and token aggregates | 90 days | 180 days |
| Audit events and integrity checkpoints | Permanent | Permanent |
When logs are removed at the end of their window, the audit event itself (timestamp, model, cost, security outcome) is kept permanently. Only the readable content is deleted. Enterprise plans carry custom retention terms. See Plans for how retention fits into each plan.
Rate-limit and usage-limit errors
| HTTP status | code | Meaning |
|---|---|---|
429 | rate_limit_exceeded | Per-key or org-level sliding-window rate limit exceeded. |
429 | usage_limit_exceeded | A configured rolling usage limit (cost / tokens / requests) was exceeded. |
413 | request_too_large | Request body exceeds 25 MB. |
402 | insufficient_balance | Prepaid balance too low to cover the estimated request cost. |
402 | payg_disabled | Paying through Gate is not enabled for this organization. |
503 | pricing_unavailable | No pricing data exists for the requested model, so the request is refused rather than served for free. |
For the full error taxonomy see Error handling.
Related pages
- Authentication: how paying through Gate vs your own keys are chosen per request.
- Error handling: full error taxonomy and debugging tips.
- Plans: how limits and retention fit into Free, Pro, and Enterprise.