Rate Limits
The gitvetrix.com API meters requests with a Redis-backed token-bucket limiter.
Each request is classified into a scope, and each scope has a per-identity
budget that depends on the caller's user group. A request that exhausts its
budget receives 429 Too Many Requests with standard rate-limit headers. For
the error envelope and other status codes see errors.md.
Scopes
Every route is labeled with one rate-limit scope. The seven canonical scopes have a configurable budget for each user group:
| Scope | Covers |
|---|---|
api.read |
Read-only REST endpoints (the default for any labeled route) |
api.write |
Mutating REST endpoints |
api.expensive |
Costly operations (large queries, presigned-URL minting, exports) |
git.read |
Git fetch / clone over HTTP |
git.write |
Git push over HTTP |
registry |
OCI, npm, PyPI, and Go module registry traffic |
beacon |
Telemetry / beacon endpoints |
One additional scope, mcp.tool_call, meters Model Context Protocol tool calls.
It is kept separate from api.write so AI-assistant traffic cannot starve REST
traffic through a shared counter. Its ceiling is governed by the
mcp.rate_limit.calls_per_min admin setting (default 120 calls per minute per
token); a value of 0 makes it inherit the api.write budget.
Budgets by user group
Three user-group tiers ship with default budgets. Custom groups created by an
operator inherit the general tier's budget until overridden. Each rule is
requests per window over a window (60 seconds for all seeded rules), with a
burst allowance and an action.
Anonymous (unauthenticated callers)
| Scope | Requests / min | Burst | Action |
|---|---|---|---|
api.read |
60 | 10 | throttle |
api.write |
10 | 0 | throttle |
api.expensive |
5 | 0 | throttle |
git.read |
30 | 5 | throttle |
git.write |
— | — | disabled (anonymous push is refused) |
registry |
60 | 10 | throttle |
beacon |
120 | 20 | throttle |
General (authenticated users)
| Scope | Requests / min | Burst | Action |
|---|---|---|---|
api.read |
600 | 60 | throttle |
api.write |
120 | 20 | throttle |
api.expensive |
30 | 5 | throttle |
git.read |
300 | 30 | throttle |
git.write |
60 | 10 | throttle |
registry |
300 | 30 | throttle |
beacon |
600 | 60 | throttle |
Admin (instance administrators)
| Scope | Requests / min | Burst | Action |
|---|---|---|---|
api.read |
6000 | 600 | allow |
api.write |
1200 | 120 | allow |
api.expensive |
300 | 30 | allow |
git.read |
3000 | 300 | allow |
git.write |
600 | 60 | allow |
registry |
3000 | 300 | allow |
beacon |
6000 | 600 | allow |
The admin tier uses the allow action: requests are metered but not
throttled, so an administrator is never locked out by a rule. There is no
hardcoded bypass — the behavior comes entirely from the seeded allow action.
These are the shipped defaults. An operator can change any budget, and the limits can only be narrowed (never widened) by per-repository, per-OAuth-application, per-token, and per-user overrides. When more than one applies, the smallest effective rate wins.
The 429 response
When a request exceeds its budget under a throttle rule, the API returns
429 Too Many Requests with the standard error envelope and the following
headers:
| Header | Meaning |
|---|---|
X-RateLimit-Limit |
The budget (requests per window) for this scope |
X-RateLimit-Remaining |
Requests left in the current window |
X-RateLimit-Reset |
Unix timestamp (seconds) when the window resets |
X-RateLimit-Scope |
The scope this request was metered against |
Retry-After |
Seconds to wait before retrying (minimum 1) |
The X-RateLimit-* headers are also emitted on throttled responses that were
allowed (still within budget), so a client can observe how close it is to a
limit. Retry-After is present only when the request was actually denied.
A well-behaved client reads Retry-After and backs off for at least that many
seconds before retrying.
Operational behavior
- Redis-backed. Token buckets live in Redis, keyed per identity and scope, so limits hold across every API node.
- Fail-open. If Redis is unreachable, requests pass through unmetered and no rate-limit headers are emitted. Tolerating an unprotected window is the deliberate tradeoff over locking everyone out.
- Kill switch. Rate limiting has a master enable switch; when it is off, every request passes without metering.
- Shadow mode. The limiter can run in shadow mode, where decisions are computed and headers are emitted but no request is actually rejected. This is used to observe the effect of a budget change before enforcing it.