Safeguard
Security Guides•

GraphQL batching and rate limits: how brute force slips through

A limit of three logins per minute means little if one GraphQL request carries hundreds. Count operations, not requests. Here is how to fix it.

Safeguard Security Team
3 min read

If your rate limiter counts HTTP requests, a GraphQL API that allows batching can be brute forced inside a single request. Count operations instead, cap how many a request may carry, and block batching on sensitive objects such as login.

The scenario

OWASP's API2:2023 describes it. A login mutation is rate limited to three requests per minute. Attackers send many login attempts in one batched GraphQL request, each with a different password. The limiter sees one request. The server processes hundreds of guesses.

OWASP's resource consumption page gives a related case: rate limits and file size checks bypassed by batching many upload operations in one request, which exhausts server memory.

Why it happens

Most gateways and middleware count at the HTTP layer. GraphQL lets a client send an array of operations, or use aliases to call the same field many times in one query. The limiter was built for a world where one request meant one action.

What the GraphQL cheat sheet recommends

The OWASP GraphQL cheat sheet addresses batching directly:

  • Add per-object rate limits in code.
  • Block batching for sensitive objects.
  • Limit how many operations run at once.

It also covers related limits: cap query depth, cap how many items a single field can request, use pagination, and set timeouts. It says timeouts alone are often insufficient, and the right value varies by API.

A fix plan

  1. Find where limits live. Gateway, resolver or both.
  2. Count operations. Include aliases and batched array entries in the count for each user and endpoint.
  3. Cap batch size. Pick a small number that matches real client behavior.
  4. Protect sensitive mutations separately. Login, reset, code verification and anything that pays or sends messages get a per-account limit that ignores how requests are packaged.
  5. Disable batching where you do not use it.
  6. Test. Send one request with many aliased login attempts against a test account and confirm the limit fires.

Related controls

  • Depth limits and amount limits stop overly large queries.
  • Disable introspection in production, as the cheat sheet advises, and consider turning off field suggestions.
  • Check authorization on every object, including edges and nodes, to prevent BOLA and BFLA.

For the broader limits list, see the API resource limits checklist. For auth specific throttles, see throttling reset and OTP endpoints.

Quick check

Do aliases count as batching?

For rate limit purposes, yes. A query that calls the same mutation under many aliases performs many operations in one request, so your counter should include them.

Is a gateway limit enough?

Not if it counts only HTTP requests. Add operation level counting in the GraphQL layer.

Safeguard's free scan at gold.safeguard.sh/scan and dependency scanning cover the GraphQL server libraries you run, and policy gates can require limit tests in pull requests.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.