Rate Limits & Complexity
Understand how the GraphQL API meters and throttles requests.
Rate Limits
1,000 pts
Max query complexity
100,000 pts
Points per minute
2,500
Requests per minute
Calculating Complexity
Each requested property costs 1 point by default. Certain query types add a performance cost on top.
With performance cost — 6 points
query {
CatalogContent {
id
title
slug
}
}
// 1(id) + 1(title) + 1(slug) + 3(performance cost) = a 6 point querySimple query — 2 points
query {
CurrentUser {
firstName
lastName
}
}
// 1 (firstName) + 1 (lastName) = a 2 point queryRate Limit Headers
| Header | Description |
|---|---|
| X-RateLimit-Remaining | Points remaining in the current window |
| X-RateLimit-Reset | Timestamp when points reset |
| Retry-After | Seconds to wait (only after exceeding limit) |
| X-Complexity-Cost | Complexity points consumed by the query |
| X-Complexity-Limit | Maximum complexity points allowed per query |
Handling Rate Limits & Complexity in Code
Read the response headers after each request to track your remaining points, monitor query complexity, and back off automatically when throttled.
async function queryGraphQL(query, variables = {}) {const response = await fetch("https://your-instance.thoughtindustries.com/helium",{method: "POST",headers: {"Content-Type": "application/json",Authorization: "Bearer YOUR_API_KEY",},body: JSON.stringify({ query, variables }),});// Rate-limit headersconst remaining = parseInt(response.headers.get("X-RateLimit-Remaining"), 10);const retryAfter = response.headers.get("Retry-After");// Complexity headersconst complexityCost = parseInt(response.headers.get("X-Complexity-Cost"), 10);const complexityLimit = parseInt(response.headers.get("X-Complexity-Limit"), 10);if (response.status === 429) {const waitSeconds = parseInt(retryAfter, 10) || 60;console.warn(`Rate limited. Retrying in ${waitSeconds}s.`);await new Promise((resolve) =>setTimeout(resolve, waitSeconds * 1000));return queryGraphQL(query, variables);}const data = await response.json();if (data.errors?.some((e) => e.message?.includes("complexity"))) {console.error(`Query too complex: ${complexityCost}/${complexityLimit} points. Simplify the query.`);return data;}if (remaining < 1000) {console.warn(`Rate limit low: ${remaining} points remaining.`);}if (complexityCost > complexityLimit * 0.8) {console.warn(`High complexity: ${complexityCost}/${complexityLimit} points used.`);}return data;}