API7 Gateway 3.10.6: Govern GraphQL by Query Cost

September 8, 2026

Products

Key Takeaways

  • Request-count limits treat a small GraphQL lookup and a deeply nested query as equal, even though their backend cost can be very different.
  • API7 Gateway 3.10.6, released on August 25, 2026, adds cost-aware enforcement to graphql-limit-count.
  • Teams can measure work by query depth, parsed complexity, or argument-driven node_quantifier, then scale the result with score_factor.
  • max_cost rejects a single over-budget query before it reaches the upstream, while X-Graphql-Query-Cost makes the charged cost visible when quota headers are enabled.
  • Service-level graphql_cost_decorations let API owners weight fields and pagination arguments without editing every route.
  • Variable resolution and bounded fragment expansion close two paths that could otherwise hide expensive work or consume gateway CPU.

Traditional rate limiting asks a simple question: how many requests did this client send? That works well when requests to an endpoint have roughly similar cost. GraphQL changes the unit of work. One request may fetch a single identifier; another may traverse several relationships and ask each field for dozens of objects.

A counter that charges both requests as one protects request volume, but not backend capacity. The same /graphql endpoint can carry radically different database, network, and resolver workloads.

API7 Gateway 3.10.6 turns that mismatch into an enforceable gateway policy. The graphql-limit-count plugin can calculate a query cost before proxying the request, charge that cost against a time-window quota, and block a single query whose cost exceeds an explicit ceiling.

This is not a replacement for resolver timeouts, database safeguards, or application authorization. It is an earlier resource-governance layer: the gateway evaluates the GraphQL document and applies a consistent budget before expensive work reaches the service.

flowchart LR
    request[GraphQL Request] --> parse[Parse Document and Variables]
    parse --> cost[Calculate Query Cost]
    cost --> quota{Within Quota and max_cost?}
    quota -->|Yes| upstream[GraphQL Service]
    quota -->|No| reject[Reject Before Upstream]

    decorations[Service Cost Decorations] --> cost

Request Count Is the Wrong Abstraction for Unequal Work

REST APIs often expose different resources and operations through distinct paths and methods. That gives an API gateway useful signals for assigning separate policies. GraphQL commonly concentrates many operations behind one HTTP endpoint, with the requested fields, nesting, fragments, and arguments carried inside the document.

Two calls to /graphql can therefore look identical to a path-based rate limiter while producing very different work. A shallow viewer lookup might touch one resolver. A nested product query can multiply work through collections, related entities, and pagination arguments such as first: 100.

This is why GraphQL governance needs two controls rather than one:

  1. A cumulative quota limits how much calculated work a client can consume during a time window.
  2. A per-query ceiling prevents one document from spending too much of that budget—or reaching the upstream at all.

API7 Gateway applies both controls in the gateway. The existing fixed-window behavior remains, but the unit charged to the counter can now represent query work rather than a flat request.

Choose a Cost Model That Matches the Risk

The GraphQL Limit Count plugin supports three cost_strategy values. They answer different operational questions.

  • depth charges by the maximum selection-set nesting depth. It remains the default, so existing configurations preserve their prior behavior after upgrading.
  • complexity scores the parsed nodes in the document. Each node combines the cost of its children with additive and multiplicative weights, making breadth as well as nesting visible.
  • node_quantifier focuses on nodes whose configured cost decorations can resolve a quantity from arguments such as first. It is useful when list cardinality is the strongest predictor of backend work.

The plugin converts the raw score into an integer charged cost. score_factor scales that value so teams can map the plugin's score onto an operational budget. One detail matters during calibration: for complexity and node_quantifier, the plugin adds 0.01, applies score_factor, and rounds up. With the default factor, a raw integer score of 3 is therefore charged as 4. The depth strategy does not add 0.01, but it still applies the factor and rounds up.

That behavior makes staging measurements important. Do not copy a threshold from a theoretical query model and assume it matches production traffic. Observe representative documents, compare their reported costs with resolver and database load, and then choose a quota and ceiling that preserve legitimate workloads.

Turn Calculated Cost Into an Enforceable Budget

Cost calculation becomes useful when it produces clear decisions. API7 Gateway 3.10.6 provides two related enforcement points.

The count and time_window settings define the cumulative fixed-window budget. A query consumes its calculated cost from that budget rather than always consuming one unit. Teams can continue to key the counter by client address, consumer identity, or another supported variable, and can use local or Redis-backed policies according to their gateway topology.

The new max_cost setting applies a ceiling to one document. If the charged cost is greater than the configured value, the gateway returns 403 Forbidden before sending the query upstream. Setting max_cost to 0 disables this per-query check.

There is an important accounting rule: the plugin charges the calculated quota before it evaluates max_cost. A query rejected for exceeding the single-query ceiling still consumes its cost from the time-window budget. Operators should account for that behavior when choosing alert thresholds and when explaining rejected requests to API consumers.

When show_limit_quota_header is enabled, the response includes X-Graphql-Query-Cost. That gives client teams and platform operators a shared number for understanding why one document consumes more quota than another. It also creates a practical calibration loop: collect costs in staging, group them by operation, and compare them with upstream latency and resource use before tightening production limits.

Model Business Cost at the Service Boundary

GraphQL syntax alone cannot reveal every expensive field. A resolver that performs a simple in-memory lookup and one that fans out to a remote system may look similar in the document. API owners need a way to add service knowledge to the generic cost model.

API7 Gateway 3.10.6 adds graphql_cost_decorations as a service-level subresource. A decoration identifies a GraphQL location through field_path, such as Query.products, Product, or a longer field chain, and adjusts how matching nodes contribute to cost.

  • add_value adds a fixed amount to the node itself.
  • mul_value multiplies the cost of the node's children.
  • add_arguments adds selected argument values to the node's own cost.
  • mul_arguments uses selected argument values as multipliers for descendant cost.

For example, a decoration for Query.products can treat first: 10 as a multiplier rather than charging the same amount as first: 1. Only one decoration may target a given field_path within a service.

Keeping decorations on the service makes the policy reusable across its routes. API owners can update the cost model without rewriting every route that carries graphql-limit-count, while gateway operators can keep enforcement and counter configuration at the traffic-policy layer.

Treat Schema Introspection as a Controlled Dependency

Matching cost decorations to a query requires the upstream GraphQL schema. For a decorated service, each gateway worker introspects the schema on its first applicable request and caches the result until the plugin reloads. Routes without decorations do not trigger introspection.

By default, the plugin derives the introspection destination from the upstream. introspection_endpoint can point to a different HTTP or HTTPS endpoint, and introspection_headers can provide the credentials that endpoint requires. Those credentials come from configuration rather than the client request because the cached schema is reused across callers handled by that worker.

This dependency belongs in the rollout plan. Validate that every gateway instance can reach the introspection endpoint, that the configured credential has only the access it needs, and that schema changes are followed by the reload required to refresh the cache. If Data Plane encryption is enabled, introspection_headers are stored encrypted at rest.

Without cost decorations, complexity can use its default node weights without schema introspection. node_quantifier, however, needs matching decorations and usable quantity arguments; without them, its raw score is 0, which becomes a charged cost of 1 with the default scaling behavior.

Resolve Variables Before They Hide Quantity

GraphQL clients commonly move argument values into variables. A policy that inspects only the document text could see first: $pageSize without knowing whether the caller requested 10 items or 10,000.

resolve_variables is enabled by default in API7 Gateway 3.10.6. The plugin resolves supplied variables, defaults declared by the GraphQL operation, and argument defaults from the upstream schema before calculating cost. This makes an argument-driven policy evaluate the value that the service is expected to use.

Disabling variable resolution can underestimate queries that provide quantifiers through variables. Keep it enabled unless a tested compatibility constraint requires otherwise, and include variable-heavy operations in the staging corpus used to set thresholds.

Bound Fragment Expansion Before It Consumes the Gateway

Cost-aware governance must also be safe for the gateway that performs the calculation. Before 3.10.6, mutually expanding GraphQL fragments could be expanded again at every reference. A small document could therefore drive unbounded CPU work during inspection; the release notes describe a 1.4 KB document with a 34-fragment chain holding a worker at full load for more than 45 seconds.

API7 Gateway 3.10.6 calculates each fragment once. A document whose fragment expansion forms a cycle is rejected with HTTP 400. This fix matters independently of the chosen cost strategy: a policy engine cannot protect an upstream if parsing the policy input can itself monopolize the gateway worker.

The boundary is now clearer. Valid fragments contribute to the cost calculation, repeated references do not trigger unlimited expansion work, and cyclic graphs fail before proxying.

What to Validate Before Enabling Cost-Aware Limits

Use the GraphQL rate-limiting guide together with the 3.10.6 release notes and plugin documentation, then validate the policy against real operations:

  1. Inventory persisted operations and representative ad hoc queries, including nested selections, fragments, aliases, and variable-supplied pagination arguments.
  2. Choose depth, complexity, or node_quantifier according to the workload signal you need; preserve depth where the existing policy is already effective.
  3. Record X-Graphql-Query-Cost in staging and correlate it with resolver latency, database queries, downstream calls, and response size.
  4. Calibrate score_factor, the time-window count, and max_cost with the plugin's rounding and charge-before-reject behavior in mind.
  5. Define graphql_cost_decorations with the GraphQL service owners, and keep each field_path unique within the service.
  6. Test schema introspection reachability, credentials, cache refresh behavior, and failure handling on every gateway instance.
  7. Verify local or Redis-backed counter scope across all gateway nodes and consumer identities that should share a budget.
  8. Exercise repeated and cyclic fragments and confirm invalid documents return HTTP 400 without degrading unrelated routes.

Govern the Work, Not Just the Request

GraphQL flexibility moves the real unit of resource use inside the request body. Treating every call as equal leaves an API platform blind to the difference between a small lookup and a query that multiplies work across fields and collections.

API7 Gateway 3.10.6 gives teams a more useful control point. It calculates cost before proxying, combines cumulative quotas with a per-query ceiling, lets service owners describe expensive schema paths, resolves variable-driven quantities, and bounds fragment processing at the gateway.

The result is not a universal GraphQL cost formula. It is a policy framework that teams can calibrate against their own resolvers and capacity. Read the complete API7 Gateway 3.10.6 release notes, review the GraphQL Limit Count plugin, and turn representative query costs into tested production budgets.

Tags:
Share article link