Skip to content

Rate Limiting

WarmHub enforces rate limits on write operations to protect platform stability. Rate limits are applied per-user and per-organization, enforced transactionally inside mutations. Read operations are not rate limited.

Limits are scoped in two ways:

ScopeKeyDescription
Per-userUser IDProtects against individual abuse. Applied to repo-scoped writes on the free tier; on paid tiers, the org limit governs instead. Standalone operations (org creation, PAT creation) are always per-user regardless of tier.
Per-orgOrg IDShared budget across all org members. Tier-aware — paid orgs get higher limits.

Only resource-creating and high-cost write operations are rate limited. Operations on existing resources (pause, revoke, rename, delete) are not — they’re self-limiting since you can only act on what already exists.

OperationScopeStrategy
Commits (things, assertions)Per-user + per-orgToken bucket
Shape creationPer-orgToken bucket
Subscription creationPer-orgToken bucket
Credential set creationPer-orgFixed window
Repository creationPer-orgFixed window
Organization creationPer-userFixed window
PAT creationPer-userFixed window

All organizations start on the free tier. Limits increase with higher tiers:

TierCommits/minRepos/hrShapes/minSubscriptions/minCredentials/hr
Free120 (user) / 600 (org)20402020
Pro1,000 (org)50603050
Enterprise5,000 (org)200200100200

On paid tiers, limits are only enforced at the org level.

When a rate limit is exceeded, the API returns HTTP 429 with a RATE_LIMITED error:

HTTP/1.1 429 Too Many Requests
Retry-After: 12
Content-Type: application/json
{
"error": {
"code": "RATE_LIMITED",
"message": "Rate limit exceeded"
}
}

The Retry-After header indicates the number of seconds to wait before retrying.

When you receive a 429 response:

  1. Read the Retry-After header — wait at least that many seconds before retrying
  2. Use exponential backoff as a fallback if the header is missing
  3. Don’t retry immediately — rapid retries consume tokens and extend the wait

The SDK classifies RATE_LIMITED errors as retryable:

try {
await client.commit.apply('acme', 'world', 'sdk', 'add data', ops)
} catch (e) {
if (e instanceof WarmHubError && e.kind === 'RATE_LIMITED') {
// safe to retry after backoff
}
}

The CLI does not auto-retry on rate limits. If a command fails with RATE_LIMITED, wait and retry manually.

MCP tool errors include backendCode: "RATE_LIMITED" when rate limited. MCP clients should treat this as retryable and apply backoff before retrying the tool call.

  • All read operations — queries, HEAD, history, search
  • Operations on existing resources — pause, resume, delete, rename, revoke
  • Internal action lifecycle — lease management, delivery arbitration