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
Rate limit headers are present when a limit applies to the request, so your client can track headroom without waiting for a rejection. They describe rate limiting only: a refusal for any other reason, such as a balance refusal, does not carry them. A request with no org limit and no per-key limit carries none of them. Which headers appear depends on which limit applied, and on whether the request was allowed or rejected.
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 and the request is allowed, two extra headers carry the org window. The per-key headers, if a per-key limit also applies, describe the key’s own window:
X-RateLimit-Org-Limit: 1000X-RateLimit-Org-Remaining: 823When the org limit is what rejects the request, the 429 carries the org window in the generic headers plus the scope, and no X-RateLimit-Org-* pair:
X-RateLimit-Limit: 1000X-RateLimit-Remaining: 0X-RateLimit-Reset: 1749254400X-RateLimit-Scope: org| 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 on an org-level rejection, passthrough-ip on every keyless BYOK passthrough request. 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. Present when the org limit is configured and the request was allowed; a rejection reports the same window in X-RateLimit-Remaining instead. |
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 not self-serve: the gatewayRateLimit field on the org’s entitlements row is the source of truth, and only Gate operators can set it. Ask support for the cap you need. null, the default, means no org cap is applied and only per-key limits are in play.
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) | 100 MB per request body on Gate’s hosted gateway |
| Dashboard API (configuration calls) | 10 MB per request body |
The gateway cap is an operator setting per deployment (GATEWAY_MAX_BODY_SIZE), not a fixed product number: Gate’s hosted gateway admits 100 MB, and a self-hosted gateway that leaves the variable unset falls back to 25 MB. Long agentic conversations that resend the whole thread, plus large tool-result blobs, are what approach it. Exceed the cap and the gateway returns HTTP 413 with code request_too_large and the enforced value in the body’s limit field, so a client can read the active ceiling instead of assuming one.
Data retention
Every request is recorded, and the different kinds of data Gate keeps have different lifetimes. Retention is not a plan feature: the readable-content window is the same for Free and Pro.
| Data | Retention |
|---|---|
| Readable content: request and response bodies, turn content, security-decision payloads | 90 days |
| Metrics: activity, cost, and token aggregates | Kept for the life of the organization |
| Audit events and integrity checkpoints | Permanent |
The 90-day window is the platform default and can be overridden per organization, shorter or longer, by Gate operators; Enterprise agreements are where a different window is usually agreed. When readable content is reaped at the end of its window, the audit event itself (timestamp, model, cost, security outcome) is kept permanently and its inclusion proof keeps verifying. Only the readable content is deleted.
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 the gateway’s configured cap. The enforced value is in the body’s limit field. |
402 | insufficient_balance | Prepaid balance too low to cover the estimated request cost. |
429 | payg_reserved | The balance covers the request, but your other in-flight requests hold it. Retry after Retry-After. |
503 | auth_unavailable | Gate could not check the API key right now. Not throttling and not a bad key. Retry after Retry-After. |
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: which limits are a plan feature and which are not.