Rate limits per surface
Rate limits are attached to individual platform surfaces. There is no source-backed universal per-tenant rate, burst multiplier, tier multiplier, or response-header set across all APIs.
Published limits
| Surface | Scope | Default limit |
|---|---|---|
| Commerce storefront, general routes | Client IP and SDK key plus route class | 100 requests/minute at each layer |
| Commerce storefront, authentication routes | Client IP and SDK key | 10 requests/minute at each layer |
| Reporting API | Client IP | 120 requests/minute |
| External-agent signup | Client IP | 20 requests/hour |
| External-agent signup | Authenticated owner | 3 signups/day |
| Agentic Commerce, Core or unknown tier | Resolved request scope | 100/minute and 1,000/hour |
| Agentic Commerce, Growth | Resolved request scope | 300/minute and 5,000/hour |
| Agentic Commerce, Scale, Enterprise, or Practice | Resolved request scope | 1,000/minute and 20,000/hour |
The reporting limit can be changed with REPORTING_RATE_LIMIT_PER_MINUTE. External-agent owner limits can be changed with EXTERNAL_AGENT_SIGNUP_DAILY_LIMIT. Agentic Commerce defaults can be changed with the AGENTIC_RATE_LIMIT_* configuration variables.
Shared per-IP limiter
Reporting and the Commerce storefront IP layer use shared/middleware.NewRateLimiter, an in-process sliding-window limiter. It keys on X-Forwarded-For when present and otherwise uses the request remote address.
When exhausted, it returns:
HTTP/1.1 429 Too Many RequestsRetry-After: 60
{"error":"rate limit exceeded"}The shared implementation does not emit X-RateLimit-Remaining or X-RateLimit-Reset.
Storefront SDK-key limiter
Commerce also limits each SDK key and route class. It uses a Redis fixed window when Redis is available and an in-memory sliding-window fallback otherwise.
An exhausted SDK-key budget returns 429 with error code sdk_key_rate_limited and a computed Retry-After. A Redis failure returns 503 with rate_limiter_unavailable rather than allowing the request without enforcement.
Both storefront layers apply, so a request must have capacity in its client-IP budget and its SDK-key budget.
GraphQL fields
GraphQL does not have one global request limit. Selected fields declare @rateLimit(max: ..., window: ...) in their schema. Examples include Accounting AI fields, Commerce mutations and Studio storefront builds.
Use the GraphQL operation reference for the exact directives on each current operation.
MCP actions
The public MCP runtime does not publish a global requests-per-second contract. Its policy can enforce a tenant’s daily T3-action budget; an exhausted budget is returned as INBLACK_RATE_LIMITED. See Tool errors for the MCP error shape.
Retry guidance
- Honor
Retry-Afterwhen it is present. - Apply exponential backoff with jitter when a surface does not provide an exact retry delay.
- Bound retries and preserve idempotency keys for writes.
- Treat
503 rate_limiter_unavailableas a transient infrastructure failure, not as available quota.