---
title: API rate limits
sidebar_label: Rate limits
sidebar_position: 7
description: Requests per second and concurrent request ceilings, why concurrency is the binding limit, heavy routes, load shedding, and what to do on a 429.
keywords: [rate limits, 429, rate_limited, concurrency, throttling, load shedding]
---

# Rate limits

Credits bound what you spend. These bound how fast you can spend it, and they
are separate on purpose: a funded account with a runaway loop is still a
runaway loop.

| Limit | What it bounds | On breach |
| --- | --- | --- |
| Requests per second | How fast requests arrive | `429 rate_limited` |
| Concurrent requests | How many run **at once** | `429 too_many_concurrent` |
| Credits per minute | Spend rate, regardless of balance | `429 cost_ceiling` |
| Heavy routes | Their concurrency, shared across **all** keys | `503 server_busy` |

## Why concurrency is the one that matters

Requests per second bounds *arrival*. Concurrency bounds *simultaneous work*.
Ten requests a second that each finish in 20 ms is nothing; a handful that each
hold an expensive query open for seconds is not. If you tune one number, tune
this one.

## Heavy routes

A few routes cost far more to serve than the rest. The [cost
table](./reference.mdx#cost-table) marks them with a dagger and their price says
so, and their concurrency is two in flight across **all** keys, not per key — so
a refusal there can mean someone else is mid-call rather than that you did
anything wrong.

A heavy route under pressure answers **`503 server_busy`** with `Retry-After`,
the same refusal the whole surface gives when it sheds load — not a `429`.
Nothing is charged. Honour the `Retry-After` and it clears.

## Load shedding

Under pressure, a metered request may be refused with `503 server_busy` and
`Retry-After: 2`. It is **charged nothing**.

## If you keep hitting a limit

Twenty refusals in a minute auto-suspends the key for fifteen minutes.

We suspend the **key**, not your address. A firewall ban would take out everyone
behind your egress, and a browser challenge is not something an API client can
solve — so a paying customer who misconfigures a loop gets a pause, not an
outage.
