Limiting GraphQL Query Depth the Right Way

Published: (January 15, 2026 at 02:20 PM EST)
3 min read
Source: Dev.to

Source: Dev.to

Introducing graphql‑safe‑depth

GraphQL is powerful, flexible, and expressive — but that flexibility can become a liability if queries are not properly constrained.
Overly deep queries can cause excessive resolver execution, high memory usage, or even denial‑of‑service scenarios.

In this post you’ll learn:

  • Why deep GraphQL queries are a real problem
  • Why many existing depth‑limit solutions fall short
  • How graphql‑safe‑depth approaches the problem differently
  • How to use it with Apollo Server and NestJS
  • When and how to combine it with other security measures

🚨 The problem: Deep GraphQL queries

query {
  user {
    posts {
      comments {
        author {
          profile {
            avatar {
              url
            }
          }
        }
      }
    }
  }
}

At first glance this looks harmless, but it can:

  • Trigger N+1 query explosions
  • Consume significant CPU and memory
  • Become a DoS vector, intentionally or not

GraphQL does not impose any default depth or complexity limits.

🤔 Why existing solutions fall short

IssueDescription
❌ Counting fields instead of execution depthSome libraries count the total number of fields rather than the deepest execution path, leading to false positives or confusing behavior.
❌ Breaking introspectionIntrospection queries (__schema, __type, __typename) are often deep by nature and should not be blocked.
❌ Hard to reason aboutCertain implementations are difficult to customize, debug, or explain to a team.

✅ The approach: graphql‑safe‑depth

graphql‑safe‑depth is a lightweight GraphQL validation rule focused on one thing:

  • 🧠 Measure the deepest resolver path
  • 🔍 Ignore introspection fields by default
  • 🧩 Fully support fragments
  • ⚡ Zero runtime dependencies
  • 🛠 TypeScript‑first, JavaScript‑friendly

How it works

  1. The library hooks into GraphQL’s validation phase.
  2. It traverses the query AST.
  3. It calculates depth based on nested field selections.
  4. It tracks the maximum execution depth.
  5. If the depth exceeds maxDepth, the query is rejected before execution.

Depth calculation example

✅ Valid query (depth = 3)

query {
  user {
    profile {
      name
    }
  }
}

❌ Invalid query (depth = 4)

query {
  user {
    profile {
      address {
        city
      }
    }
  }
}

Only the deepest execution path matters — not the total number of fields.

🚀 Usage examples

Apollo Server (Node.js)

import { ApolloServer } from "apollo-server";
import { createDepthLimitRule } from "graphql-safe-depth";

const server = new ApolloServer({
  typeDefs,
  resolvers,
  validationRules: [
    createDepthLimitRule({ maxDepth: 3 }),
  ],
});

Apollo Server (NestJS)

import { createDepthLimitRule } from "graphql-safe-depth";

GraphQLModule.forRoot({
  autoSchemaFile: true,
  validationRules: [
    createDepthLimitRule({ maxDepth: 3 }),
  ],
});

⚙️ Configuration options

createDepthLimitRule({
  maxDepth: number;               // required
  ignoreIntrospection?: boolean; // default: true
  message?: (depth: number, maxDepth: number) => string; // optional
});
  • maxDepth – The maximum allowed execution depth.

    createDepthLimitRule({ maxDepth: 3 });
  • ignoreIntrospection – When true, introspection fields are ignored.

    createDepthLimitRule({
      maxDepth: 3,
      ignoreIntrospection: false,
    });
  • message – Custom validation error message.

    createDepthLimitRule({
      maxDepth: 3,
      message: (depth, max) =>
        `Query depth ${depth} exceeds the allowed maximum of ${max}`,
    });

🔐 Security considerations

Depth limiting is not a silver bullet, but it works well together with:

  • ✅ Query complexity limits
  • ✅ Proper authentication & authorization
  • ✅ Rate limiting
  • ✅ Caching and batching (e.g., DataLoader)

graphql‑safe‑depth focuses on doing one thing well — preventing dangerously deep queries in a predictable way.

📦 Installation

npm i graphql-safe-depth
  • GitHub repository:
  • npm package:

🧠 Final thoughts

The library started as a learning exercise and has evolved into a production‑ready tool with a stable v1.0.0 release. If you’re running GraphQL in production and need a simple, predictable depth limit, graphql‑safe‑depth may be a good fit.

Feedback, issues, and contributions are very welcome! 🙌

Back to Blog

Related posts

Read more »

My Node.js API Best Practices in 2025

Node.js has been powering production APIs for well over a decade now, and in 2025 it’s no longer “new” or experimental, it’s infrastructure. That maturity has c...

Stop Writing APIs Like It's 2015

We're in 2025, and many codebases still treat APIs as simple “endpoints that return JSON.” If your API design hasn’t evolved past basic CRUD routes, you’re sacr...