Back to results for “Security”
Node.js › GraphQL

How would you implement query complexity analysis or depth limiting in a GraphQL API to prevent a maliciously deep or expensive query from overwhelming the server?

Advanced

Answer

Because GraphQL lets clients compose arbitrarily deep and nested queries (potentially combined with an N+1-triggering pattern across many levels), a malicious or careless client could construct a query that's computationally very expensive to resolve -- query complexity analysis assigns a cost to each field (based on factors like expected result size) and rejects queries exceeding a configured total budget before execution even begins, while depth limiting simply caps how many levels of nesting a query is allowed to have, both providing protection against this specific denial-of-service vector unique to GraphQL's flexible querying model.
const depthLimit = require('graphql-depth-limit');
const { createComplexityLimitRule } = require('graphql-validation-complexity');

const server = new ApolloServer({
  typeDefs, resolvers,
  validationRules: [depthLimit(5), createComplexityLimitRule(1000)],
});
Real-world example A public GraphQL API adds a depth limit of 5 and a complexity limit of 1000 after discovering a malicious actor had been submitting deeply nested queries specifically designed to trigger an exponential number of database calls, effectively performing a denial-of-service attack through legitimate-looking GraphQL syntax.

Common follow-ups: How do you determine an appropriate complexity budget without being so restrictive it blocks legitimate, genuinely complex client queries?;What's the relationship between this protection and the N+1 problem DataLoader addresses -- are they solving the same or different issues?