# Rate limits & usage

> Per-key rate limits, what counts as an operation, and plan caps on operations, storage and primitives.

Source: https://useprimitives.com/docs/api/limits

## Rate limits

The cloud API rate-limits by plan. Each API key (or OAuth grant) has its own bucket, and so does its workspace, so adding keys doesn't add capacity:

| Plan | Requests per second | Burst |
| --- | --- | --- |
| Starter | 20 | 60 |
| Pro | 100 | 300 |
| Team | 500 | 1,500 |
| Enterprise | 1,000 | 3,000 |

The burst is how many requests a key can send at once after idling. Separately, every client IP is limited to 500 requests per second (burst 1,500) before authentication, and [signed URLs](/docs/api/signed-urls) are limited to 20 requests per second (burst 60) per IP. Over a limit the API answers `429 rate_limited` with a `Retry-After` header in seconds. Both SDKs retry `429` with backoff. The local engine doesn't rate-limit. `RateLimit-*` headers are coming soon.

## Usage and limits

On Primitives Cloud, usage is measured in **operations**. An operation is any call that touches a primitive's data or lifecycle through REST, the SDKs or MCP:

- Every route under `/v1/primitives/{id}/…`: database `query`, `exec` and `batch`, files, queues, memories, vaults (including `fetch`), keys, objects (including `presign`), and snapshots, fork, restore, pause, resume, export and stats (but not `audit`).
- Every MCP `tools/call` of a primitive tool. Each call in a JSON-RPC batch counts on its own.
- Every successful request through a [signed URL](/docs/api/signed-urls).

These are not operations: creating a primitive (`POST /v1/primitives` or `primitive_create`), `GET /v1/groups` and the other group routes, reading the audit trail (`GET /v1/audit` and `/v1/primitives/{id}/audit`), listing primitives with `GET /v1/primitives`, the `primitive_list` MCP tool, API key management, MCP `initialize` and `tools/list`, and dashboard page loads. Queue messages aren't a separate limit; sending and receiving them are operations like any other.

| Plan | Operations / month | Storage | Primitives |
| --- | --- | --- | --- |
| Starter | 1M, hard cap | 5 GB, hard cap | 100, hard cap |
| Pro | 25M included, then $0.50 per extra 1M | 50 GB included, then $0.25 / GB-month | Unlimited |
| Team | 250M included, then $0.40 per extra 1M | 250 GB included, then $0.20 / GB-month | Unlimited |
| Enterprise | Custom | Custom | Unlimited |

On Starter, requests over a cap are refused, never billed. Once the workspace has used its 1M operations for the month, further operations get `429 plan_limit`:

```json
{
  "error": {
    "code": "plan_limit",
    "message": "This workspace used its 1M operations for this month on the Starter plan. Upgrade to Pro or wait until 2026-11-01."
  }
}
```

At 5 GB of storage, write operations get `429 plan_limit`: database `query`, `exec` and `batch` (any SQL statement can write) and creating a branch, file writes, moves, `mkdir` and directory forks, queue sends and topic publishes, `remember`, `supersede` and `consolidate`, setting a secret or creating a grant, setting or incrementing keys, putting or copying objects (including uploads through a signed URL), snapshots, forks and restores, and creating a primitive (creating one isn't an operation, but it adds storage). Other reads and deletes keep working, so you can free up space. Unlike `rate_limited`, retrying with backoff won't help; upgrade or wait for the reset.

Pro and Team are never cut off. Usage beyond the included operations and storage is billed as overage. Operation counters reset on the 1st of each month, UTC.
