GraphQL rate limiting should account for the work inside an operation, not only the number of HTTP requests. One request can select many fields, traverse relationships, or ask for large lists.
Start with server-enforced bounds on returned data and operation shape. Then add client budgets that reflect estimated cost and actual service capacity. A bot assessment can inform policy, but it cannot calculate resolver cost or enforce object permissions on its own.
GraphQL's security guidance covers pagination, depth and breadth limits, and query complexity analysis. These controls address different forms of demand; none is a universal substitute for the others.
Review what a client can ask for
For each important operation, record its list sizes, relationship traversal, and expensive resolver dependencies. Include operations used by older application versions and approved integrations.
Do not assume that a shallow query is cheap. A broad selection can request many independent fields. A single expensive resolver can also dominate work even when depth is low.
Likewise, a persisted operation is not automatically safe merely because its text is stored. Review which documents are actually approved and whether client-supplied variables can expand their work beyond intended bounds.
Match each limit to its failure mode
| Control | What it bounds | What still needs review |
|---|---|---|
| Page-size cap | Items returned from a list | Number of lists selected |
| Depth limit | Nested relationship traversal | Broad shallow operations |
| Breadth or alias limit | Repeated parallel selections | Cost of each selection |
| Complexity allowance | Estimated operation work | Whether estimates match resolver behavior |
| Concurrency limit | Operations running together | Cost and duration of each operation |
| Timeout | Allowed execution duration | Whether downstream work actually stops |
Treat the table as a design worksheet. The correct combination depends on the implementation and the operations your clients need.
Keep authorization at the resource boundary. OWASP's REST guidance describes endpoint access control; for GraphQL, apply the same separation of traffic policy and access permission to the operations and resources being resolved.
Make cost estimates explainable
If you assign weights to fields, document the reason: database work, result size, or a constrained dependency. Avoid a scoring system that cannot explain why a normal operation is refused.
Compare estimated cost with observed execution time and downstream calls in a controlled environment. A schema change can make an old estimate inaccurate. Include cost review when a resolver gains a new dependency or a list changes its behavior.
Decide how variables affect cost before execution. If the calculation ignores a client-selected list size, the nominal budget may not bound the work you intended.
Review batching and retries explicitly
If the server accepts multiple operations in one HTTP request, establish whether each operation consumes an allowance. Check whether concurrent requests share the same account or tenant budget.
A retry after a timeout may arrive while earlier work is still running. Trace cancellation and duplicate mutation handling instead of assuming that the failed client request means the server did nothing.
Return an error the client understands. An HTML challenge in a GraphQL response path needs an explicit integration design; it should not appear unexpectedly inside a client expecting a structured response.
Test the approved client contract
Review a normal application screen, a mobile client, and any permitted reporting integration. Include maximum supported pagination and a rejected operation. Use synthetic data and bounded requests in an authorized environment; generating an uncontrolled load spike is unnecessary for this review.
After a change, monitor rejected operations by reason, successful completion, and backend saturation. Keep a route back to the previous configuration if approved clients break.
Use API rate-limit design for broader counting scopes and the API abuse use case for the product discussion. Bring a representative operation and its resource costs so the evaluation addresses the GraphQL workload, not just the HTTP endpoint.
