Skip to content

Rate limits

Patomic rate-limits per API key, per minute. Each key has its own rate_limit_rpm value, set at mint time and modifiable via PATCH /v1/keys/{id}.

A single SQL statement enforces the limit atomically — there is no read-then-write race window:

INSERT INTO rate_limits (key, count, window_start, expires_at)
VALUES (?, 1, ?, ?)
ON CONFLICT(key) DO UPDATE SET count = count + 1
RETURNING count;

The key is ${api_key_id}:${minute_window}. After incrementing, if count > rate_limit_rpm, the request returns 429 and the increment is preserved (so a flood of attempts after the limit doesn’t reset the counter).

Every successful response includes:

x-ratelimit-limit: 600 # your key's rpm
x-ratelimit-remaining: 587 # calls left in the current minute
x-ratelimit-reset: 1715292000 # unix epoch when the window resets

When you exceed the limit, you also get:

Retry-After: 32

…the seconds until the current window expires. Always honour Retry-After — fixed-interval retries are a footgun.

async function callPatomic(path: string, init: RequestInit = {}): Promise<Response> {
for (let attempt = 0; attempt < 5; attempt++) {
const res = await fetch(`https://patomic-api.pedrotengelmann.workers.dev${path}`, {
...init,
headers: { Authorization: `Bearer ${process.env.PATOMIC_KEY}`, ...init.headers },
});
if (res.status !== 429) return res;
const wait = Number(res.headers.get("retry-after") ?? 1) * 1000;
await new Promise((r) => setTimeout(r, wait));
}
throw new Error("rate-limited 5 times in a row — investigate");
}

Mint a second key with a higher limit, or rotate an existing one upward via PATCH /v1/keys/{id} with {"rate_limit_rpm": 6000}. There is no enterprise plan upsell wall today — limits exist to protect Patomic itself, not to extract revenue.