Rate limits
Rate limits
Per-token request limits, the headers that report them, and how to back off.
Limits are per token, over a rolling 60-second window. Ingest is deliberately generous — the constraint there is payload size and batching, not request count.
| Endpoint group | Requests / minute |
|---|---|
POST /v1/ingest/:dataset | 6,000 |
POST /v1/query | 1,000 |
GET on any resource | 2,000 |
| Everything else | 600 |
Headers
| Header | Meaning |
|---|---|
X-RateLimit-Limit | Ceiling for the current window |
X-RateLimit-Remaining | Requests left in the window |
X-RateLimit-Reset | Unix seconds at which the window resets |
Retry-After | Seconds to wait — only on a 429 |
Backing off
Node
async function ingest(events: unknown[], attempt = 0): Promise<Response> {
const res = await fetch("https://api.logstreem.com/v1/ingest/api-gateway-prod", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.LOGSTREEM_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify(events),
});
if (res.status !== 429 || attempt >= 5) return res;
const wait = Number(res.headers.get("retry-after") ?? 2 ** attempt);
await new Promise((r) => setTimeout(r, wait * 1000));
return ingest(events, attempt + 1);
}Batch instead of retrying
If you are hitting the ingest limit you are almost certainly sending one event per request. Buffer for a second and send an array — see batching.