> ## Documentation Index
> Fetch the complete documentation index at: https://docs.myme.so/llms.txt
> Use this file to discover all available pages before exploring further.

# Rate limiting

> Per-credential request caps, response headers, and how clients should back off

Every request counts against a rolling per-credential window. The server returns rate-limit headers on every response so clients can pace themselves without blind retry loops.

## Behaviour

* **Keyed by credential** — the API key id (or the caller's forwarded IP for unauthenticated bootstrap requests) identifies the bucket. Two keys on the same tenant get separate buckets.
* **Path-scoped** — the window segments by the first path component (`/items`, `/edges`, `/keys`, ...). Hitting `/items` heavily doesn't crowd out `/edges` calls.
* **Read-friendly** — `GET` requests get double the default limit. Write endpoints enforce the base limit.
* **Sensitive paths capped tighter** — `/keys` and `/auth/token` carry stricter limits regardless of the configured default.

When the window is exceeded, the server returns `429 rate_limited`. Subsequent requests in the same window continue to fail until the window resets.

## Headers

Every response (including `429`) carries:

| Header                  | Meaning                                         |
| ----------------------- | ----------------------------------------------- |
| `X-RateLimit-Limit`     | The effective limit for this request's path.    |
| `X-RateLimit-Remaining` | Requests remaining in the current window.       |
| `X-RateLimit-Reset`     | Unix timestamp when the window resets.          |
| `Retry-After`           | On `429` only. Seconds to wait before retrying. |

Clients that read `X-RateLimit-Remaining` on every response can throttle proactively without ever hitting `429`.

## Configuration

Rate limiting is on by default. Two variables tune it:

* **`RATE_LIMIT_ENABLED`** — set to `false` to disable entirely. Useful for trusted internal deployments behind their own rate-limiting proxy; otherwise leave it on.
* **`RATE_LIMIT_REQUESTS`** — requests per minute, per credential, per path prefix. Path-specific overrides (tighter caps on `/keys` and `/auth/token`) apply regardless.

See [Configuration](/self-hosting/configuration) for defaults and the full variable set.

## Client strategy

* **Branch on the error code, not HTTP status.** `err.code === "rate_limited"` is the stable signal; treat other 429s as generic.
* **Respect `Retry-After`.** It's a server-computed delay to the next window edge — retrying earlier just wastes another request.
* **Batch where possible.** `POST /items/bulk` costs one request for many items; looping `POST /items` burns the window fast.
* **Paginate with cursors, not parallel scans.** Sequential cursor pagination is cheaper than concurrent offset walks and avoids hammering the window.

SDKs can retry `429` automatically with exponential backoff + jitter bounded by `Retry-After`. The Swift SDK's `retryPolicy` and the TypeScript SDK's built-in retry middleware both honour the header.
