# Limits

The per-merchant rate limits on Kustom's APIs in production and playground, the X-Ratelimit headers that report your remaining quota, how to back off after a 429 and the 1MB request body cap.

Kustom limits both how often you may call and how large a single call may be. Rate limits are
counted per **merchant ID**, not per credential, so every server, job and retry you run shares
one quota. Every response tells you how much of that quota is left, which is what lets a
well-behaved client pace itself instead of discovering the limit by hitting it.

## Rate limits per merchant ID

Limits are measured per operation class. Creating a session is metered separately from
everything else, because it is the expensive one.

| Environment | Create-session operations | All other operations |
| --- | --- | --- |
| Production | 40 requests per second | 200 requests per second |
| Playground (testing) | 5 requests per second | 50 requests per second |

Two things follow from "per merchant ID". Issuing a second set of API credentials does not buy you more
quota. And once a merchant ID is being rate limited, *every* subsequent request from that
merchant is rejected until the window resets — including requests from a different service of
yours that was behaving perfectly.

Creating a customer token is metered as a create-session operation: 40 per second in
production, 5 per second in playground.

Kustom may change these limits to prevent abuse or to contain a misbehaving integration.
Read the headers rather than hard-coding the numbers above.

## Rate limit headers on every response

Three headers accompany every response, not only a rejected one.

| Header | What it reports |
| --- | --- |
| `X-Ratelimit-Limit` | The quota and the metering window, as `<quota>, <quota>;w=<seconds>`. |
| `X-Ratelimit-Remaining` | Approximate requests still available in the current window. |
| `X-Ratelimit-Reset` | Seconds until the current window resets. |

```http
X-Ratelimit-Limit: 40, 40;w=1
X-Ratelimit-Remaining: 15
X-Ratelimit-Reset: 1
```

That response says the quota is 40 requests per 1-second window, 15 remain in the current
window, and the window resets in 1 second. The values are approximate and best-effort — treat
`Remaining` as a signal to slow down, never as an exact budget to spend to zero.

## Handling a 429

A rate-limited request returns HTTP `429` and the headers above. Recovering from one well
takes three things:

1. **Pace against `X-Ratelimit-Remaining`.** Slow down as it approaches zero rather than
   waiting for the rejection. Spread a batch job across the whole window instead of firing it
   at the top of the second.
2. **Retry with exponential backoff plus jitter.** Without jitter, every client that was
   throttled together retries together, and throttles itself again.
3. **Control global flow with a token bucket.** One shared bucket in front of your Kustom
   client caps the rate across all your workers, which per-worker limits cannot do.

A `429` means "not now", not "invalid" — the request itself was fine, so retrying it is safe.
On an Order Management write, send an idempotency key anyway. See
[Idempotency and retries](/order-management/idempotency-and-retries/).

## Request body size limit

The maximum request body is **1MB** by default. A larger body is not processed and returns
`413 Payload Too Large`.

This bites in exactly one place in practice: an order with a very long order-line list, or a
large `attachment.body` of [extra merchant data](/basics/conventions/merchant-data/). Neither
gets truncated for you — the whole request is rejected.

## Common causes of rate limiting

| Cause | What to do about it |
| --- | --- |
| A burst of requests in a short window | Pace requests across the full interval the headers report, and retry with exponential backoff. |
| A planned traffic spike, such as a flash sale | Contact [Kustom Merchant Support](https://help.kustom.co/en/) before the event, not during it. |
| Bot traffic against your storefront | Add bot detection and require user authentication before your server calls Kustom. |

Quotas are set so that legitimate traffic from the large majority of merchants never touches
them. If you are hitting a limit routinely, the shape of the traffic is worth investigating
before the quota is.

## Related

- [Reading the 429 error body](/api/errors/) — the error object and its `correlation_id`
- [Retrying a write safely](/order-management/idempotency-and-retries/) — the idempotency key that makes a retry cost nothing
- [Trimming a request that returns 413](/basics/conventions/merchant-data/) — where large attachment bodies come from
- [Checking Kustom's current status](/basics/conventions/stability/) — availability objectives and the status page
