Skip to main content

Project rate limits for Ory Network

Each project has a set of rate limit buckets. A bucket is a named group of API endpoints that share the same rate limit thresholds. When a request comes in, Ory resolves which bucket the endpoint belongs to and applies the threshold for that bucket.

Bucket thresholds are determined by two factors:

  • Subscription tier: The project's subscription tier (Developer, Production, Growth, or Enterprise).
  • Project environment: The project's environment (Production, Staging, or Development).

For a detailed explanation of tiers and environments, see our Workspaces and environments guide.

Rate limits per bucket

Buckets follow a {service}-{access}-{threshold} naming pattern. For example:

  • kratos-public-high: for endpoints with a high rate limit allowance
  • hydra-public-medium: for endpoints with a moderate rate limit allowance
  • hydra-admin-low: for endpoints with a low rate limit allowance
info

A bucket counter is shared across all endpoints in the same bucket. For example, POST /admin/relation-tuples and  DELETE /admin/relation-tuples both belong to keto-admin-high, so every call to either endpoint counts against the same limit. Plan your request volumes accordingly.

Rate limit dimensions

You will see two rate limits for each bucket:

  • Burst limit: Maximum requests per second (rps), allowing for short traffic spikes.
  • Sustained limit: Maximum requests per minute (rpm), ensuring consistent performance over time.

Monitor rate limit headers

Ory Network includes rate limit information in API response headers for project rate-limits. Use these headers to avoid exceeding the applicable rate limit. Your client must handle these responses to maintain service quality.

HeaderDescription
x-ratelimit-limitThe rate limit ceiling(s) for the current request, including burst and sustained limits
x-ratelimit-remainingNumber of requests remaining in the current window
x-ratelimit-resetNumber of seconds until the rate limit window resets

Example header values:

x-ratelimit-limit: 10, 10;w=1, 300;w=60
x-ratelimit-remaining: 8
x-ratelimit-reset: 1

The x-ratelimit-limit header follows the IETF RateLimit header fields draft, where w=1 indicates a 1-second window and w=60 indicates a 60-second window. Use these headers to throttle requests proactively and reduce the likelihood of hitting 429 errors.

How to handle 429 responses

When your client receives a 429 Too Many Requests response, you've exceeded the applicable rate limit. Your client must handle these responses to maintain service quality.

Your implementation must:

  • Detect 429 responses: Monitor for HTTP 429 status codes on all API calls.
  • Implement exponential backoff: When receiving a 429, pause and retry with increasing delays (for example: 1s, 2s, 4s, 8s).
  • Respect rate limit headers: Check x-ratelimit-remaining and x-ratelimit-reset, when available, to throttle requests proactively.
  • Avoid retry storms: Don't retry failed requests in a tight loop.

Exponential backoff strategy

Implement an exponential backoff strategy to proactively avoid hitting rate limits.

async function callApiWithBackoff(request, maxRetries = 5) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
const response = await fetch(request)
if (response.status === 429) {
const delay = Math.pow(2, attempt) * 1000 // 1s, 2s, 4s, 8s, 16s
await new Promise((resolve) => setTimeout(resolve, delay))
continue
}
return response
}
throw new Error("Max retries exceeded")
}

Clients that repeatedly exceed rate limits without proper backoff may have their API access temporarily blocked. For high-volume use cases that exceed your plan's limits, open a support ticket via the Ory Console or email support@ory.sh.