Skip to main content

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 query

Simple query — 2 points

query {
  CurrentUser {
    firstName
    lastName
  }
}

// 1 (firstName) + 1 (lastName) = a 2 point query

Rate Limit Headers

HeaderDescription
X-RateLimit-RemainingPoints remaining in the current window
X-RateLimit-ResetTimestamp when points reset
Retry-AfterSeconds to wait (only after exceeding limit)
X-Complexity-CostComplexity points consumed by the query
X-Complexity-LimitMaximum 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 headers
const remaining = parseInt(
response.headers.get("X-RateLimit-Remaining"), 10
);
const retryAfter = response.headers.get("Retry-After");
// Complexity headers
const 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;
}