Files
supabase/apps/docs/content/_partials/api_rate_limits.mdx
T
Shane AdamsandClaude Sonnet 5.5 6c150d26d9 docs(mgmt-api): clarify rate limits are per endpoint (#51379)
## Problem

The Management API rate limits docs said limits are per user and per
project or organization. They didn't say that each endpoint also has its
own limit, or how requests without a project or organization, and tokens
versus OAuth apps, are counted. The partial also had a typo, a repeated
example, and a tracking-key sentence that listed endpoint as a scope.

## Solution

Edits to `apps/docs/content/_partials/api_rate_limits.mdx`, in one
commit per change type:

1. `docs(mgmt-api): clarify rate limits are per endpoint`: the content
change. It adds the per-endpoint model, the user scope, the `POST
/v1/projects` scoping, and who the limit applies to.
2. **Style**: fixes the `enpoint` typo and the table alignment, removes
the repeated Project A/B paragraph and the `database/context` note that
restated its table rows, unwraps hard-wrapped lines, and aligns bold
labels and wording with the style guide.
3. **Structure**: moves "Rate limit response headers" after "Who the
limit applies to", so the concept sections come before the reference
sections. No headings were renamed, and no inbound anchors to them exist
in `apps` or `packages`.
4. **Technical**: the tracking-key sentence now reads "scope (project or
organization) and the endpoint". It previously listed endpoint as a
scope, which contradicted the scope list.

Not verified against the rate limiter, which isn't in this repo. A
reviewer with access should confirm:

- Requests without a project or organization count against the user.
- `POST /v1/projects` is organization-scoped via `organization_slug`.
- Personal access tokens share the user's limit, and OAuth apps share
the app's limit.
- The tracking-key wording in commit 4 is inferred from the page, not
from code.

## Preview links

| Site | Live | Preview | Search for |
| ---- |
-------------------------------------------------------------------------------------
|
------------------------------------------------------------------------------------------------------------
| ------------------------------ |
| Docs |
[/docs/reference/api/introduction](https://supabase.com/docs/reference/api/introduction)
|
[/docs/reference/api/introduction](https://docs-git-docs-mgmt-api-rate-limits-per-endpoint-supabase.vercel.app/docs/reference/api/introduction)
| `Who the limit applies to` |

## Review instructions

1. Open the live and preview links side by side and scroll to "Rate
limits".
2. Check that the section order is: Standard rate limit, Rate limit
scope, How rate limits are tracked, Who the limit applies to, Rate limit
response headers, Endpoint exceptions, Best practices.
3. Check that the scope table and the endpoint exceptions tables render
correctly.
4. Review commit by commit, since each commit is one change type.
5. If you can read the rate limiter code, check the unverified claims
listed above.

## Checklist

Check all before review:

- [x] I have read
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
- [x] If I wrote a new docs topic or edited an existing topic, I used
the `/write-the-docs` or `/edit-the-docs` skill, which applies the docs
[style
guide](https://github.com/supabase/supabase/tree/master/apps/docs/style-guide)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-07 10:22:44 -06:00

79 lines
5.8 KiB
Plaintext

## Rate limits
Rate limits are applied to prevent abuse and ensure fair usage of the Management API. Rate limits are based on a per-user, per-scope model, meaning each user gets independent rate limits for each project and organization they interact with.
### Standard rate limit
| Limit | Duration | Scope |
| ------------ | -------- | --------------------------------------------------- |
| 120 requests | 1 minute | Per user, per project or organization, per endpoint |
When you exceed this rate limit, all further API calls return a `429 Too Many Requests` response for the remainder of the minute. Once the time window expires, your request quota resets and you can make requests again.
### Rate limit scope
Rate limits are applied with per-user, per-scope, per-endpoint isolation:
- **Project scope**: rate limits apply independently to each project.
- **Organization scope**: rate limits apply independently to each organization.
- **User scope**: requests that don't include a project or organization, such as `GET /v1/projects` and `GET /v1/organizations`, are counted against the user.
- **Endpoint**: within each scope, every endpoint has its own limit.
For example, you can make 120 requests to Project A and 120 requests to Project B within the same minute, as they are tracked separately. Within one organization, calling `GET /v1/organizations/{slug}/members` 120 times doesn't affect calls to `GET /v1/organizations/{slug}` or `POST /v1/projects` for that organization.
`POST /v1/projects` is organization-scoped, using the `organization_slug` in the request body.
### How rate limits are tracked
Your requests are identified and tracked using one of the following identifiers, in this order of priority:
1. **OAuth App ID**: If your request is authenticated via an OAuth application
2. **User ID**: If your request is authenticated with a personal access token
3. **IP Address**: If your request is unauthenticated (extracted from request headers)
Each identifier is combined with the scope (project or organization) and the endpoint to create a unique tracking key. This ensures that rate limits are isolated per user and per scope, preventing one project or organization from affecting another.
### Who the limit applies to
- **Personal access tokens**: the limit applies to the user, so all tokens created by the same user share it.
- **OAuth apps**: the limit applies to the app, shared by everyone calling through it.
### Rate limit response headers
Every API response includes rate limit information following official [HTTP specification headers](https://datatracker.ietf.org/doc/html/draft-ietf-httpapi-ratelimit-headers):
- `X-RateLimit-Limit` - The maximum number of requests allowed in the current time window
- `X-RateLimit-Remaining` - The number of requests remaining before you hit the rate limit
- `X-RateLimit-Reset` - The number of seconds remaining until your rate limit resets
You can use these headers to monitor your usage and implement proactive rate limit handling before receiving a 429 response.
### Endpoint exceptions
Some endpoints have stricter rate limits than the standard 120 requests per minute to prevent abuse of resource-intensive operations:
| Endpoint | Limit | Duration | Reason |
| ---------------------------------------------------------- | ----------- | -------- | --------------------------------------------------- |
| `GET /v1/projects/:ref/endpoints/logs.all` | 30 requests | 1 minute | Analytics log queries are computationally expensive |
| `GET /v1/projects/:ref/endpoints/usage.api-counts` | 30 requests | 1 minute | Analytics aggregation is computationally expensive |
| `GET /v1/projects/:ref/endpoints/usage.api-requests-count` | 30 requests | 1 minute | Analytics aggregation is computationally expensive |
| `GET /v1/projects/:ref/database/context` | 10 requests | 1 minute | Database context operations are resource-intensive |
| `GET /v1/projects/:ref/database/context` | 1 request | 1 second | Burst limit to prevent rapid successive requests |
| `POST /v1/projects/:ref/config/custom-hostname/initialize` | 10 requests | 1 minute | These operations are expensive |
| `POST /v1/projects/:ref/config/custom-hostname/reverify` | 10 requests | 1 minute | These operations are expensive |
| `DELETE /v1/projects/:ref/config/custom-hostname` | 10 requests | 1 minute | These operations are expensive |
| `GET /v1/projects/:ref/config/vanity-subdomain` | 10 requests | 1 minute | These operations are expensive |
Some endpoints have the standard 120 requests per minute but with different timeout durations:
| Endpoint | Limit | Duration | Reason |
| -------------------------------------------- | ------------ | --------- | ---------------------------------------------------- |
| `POST /v1/projects/:ref/database/migrations` | 120 requests | 3 minutes | Database migrations may require more processing time |
### Best practices
- **Monitor rate limit headers**: Check the `X-RateLimit-Remaining` header to see how many requests you have left. When it approaches 0, slow down your requests to avoid hitting the limit.
- **Implement exponential backoff**: When you receive a 429 response, wait before retrying. You can use the `X-RateLimit-Reset` header (seconds) to determine exactly how long to wait.
- **Batch operations**: Where possible, combine multiple operations into fewer API calls to reduce your request count.
- **Be mindful of expensive endpoints**: Analytics, database context, and domain endpoints have stricter limits, so use them sparingly.