100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace

What Is the GraphQL N+1 Problem and How Do You Solve It?

Learn what causes the GraphQL N+1 problem and how DataLoader batches per-item lookups into one query to fix it.

hardQ214 of 224 in Web Development Est. time: 6 minsLast updated:
Open Code Lab

Expected Interview Answer

The GraphQL N+1 problem happens when resolving a list field triggers one query to fetch the list plus one additional query per item to resolve a nested field, turning a single logical request into N+1 database round trips, and it is typically solved by batching those per-item lookups with a data loader that collects requests within a tick and issues one combined query.

Consider a query fetching 50 posts along with each post's author name: a naive resolver runs one query to get the 50 posts, then, because the author field resolver is called independently for each post, issues 50 separate queries to fetch each author — 51 total queries for what should logically be two. This happens because GraphQL resolvers are field-level and unaware of sibling calls by default, so each one fires its own database or service call without knowing 49 others are asking for similar data in the same tick. The standard fix is a batching-and-caching utility like DataLoader, which collects all the individual author-ID lookups requested during a single event-loop tick, deduplicates them, and issues one batched query such as WHERE id IN (...) instead of N separate ones, then resolves each original call from that single batched result. This turns 51 queries into 2, and DataLoader also caches per-request so the same ID requested twice in one query is only fetched once.

  • Collapses N+1 sequential queries into a small, fixed number of batched queries
  • DataLoader deduplicates and caches lookups within a single request
  • Keeps resolver code simple — resolvers still request one item at a time
  • Applies to any field resolving related entities, not just direct database calls

AI Mentor Explanation

The N+1 problem is like a scorer fetching the list of 11 players on a team, then separately walking to the records room 11 times, once per player, to look up each one's career average. A batching approach is like the scorer collecting all 11 names first, then making a single trip to the records room asking for all 11 averages at once. That collect-first-then-fetch-once strategy is exactly what a DataLoader does to eliminate the extra 11 trips in a GraphQL resolver.

Step-by-Step Explanation

  1. Step 1

    Query resolves the list field

    One query fetches the top-level list, e.g. 50 posts.

  2. Step 2

    Nested field resolver runs per item

    Without batching, the author resolver fires independently for each of the 50 posts, issuing 50 separate calls.

  3. Step 3

    DataLoader collects requests in a tick

    Instead of firing immediately, each author-ID request is queued into a batch within the same event-loop tick.

  4. Step 4

    One batched query resolves all requests

    DataLoader issues a single WHERE id IN (...) query and distributes results back to each original resolver call.

What Interviewer Expects

  • Clear explanation of why field-level resolvers cause N+1 by default
  • Concrete walkthrough of the query-count math (1 list query + N item queries)
  • Naming DataLoader (or equivalent batching utility) as the standard solution
  • Understanding that DataLoader also deduplicates/caches within a single request

Common Mistakes

  • Vaguely saying “use caching” without explaining the batch-collect-then-query mechanism
  • Confusing the N+1 problem with simple over-fetching, which is a different issue
  • Not mentioning that resolvers are field-level and unaware of siblings by default
  • Forgetting DataLoader's per-request caching/deduplication behavior

Best Answer (HR Friendly)

The N+1 problem happens when fetching a list of items in GraphQL accidentally triggers one extra database call per item to get related data, instead of one combined call. The standard fix is a tool called DataLoader, which waits a moment, collects all those individual requests, and fetches them together in a single batched query instead of many separate ones.

Code Example

Naive N+1 resolver vs DataLoader-batched resolver
// Naive: N+1 queries -- one per post to fetch its author
const resolvers = {
  Post: {
    author: (post) => db.query('SELECT * FROM users WHERE id = ?', [post.authorId]),
  },
}

// Batched: DataLoader collects IDs within a tick, issues one query
const authorLoader = new DataLoader(async (authorIds) => {
  const rows = await db.query('SELECT * FROM users WHERE id IN (?)', [authorIds])
  const byId = new Map(rows.map((r) => [r.id, r]))
  return authorIds.map((id) => byId.get(id)) // preserve input order
})

const resolvers2 = {
  Post: {
    author: (post) => authorLoader.load(post.authorId),
  },
}

Follow-up Questions

  • How does DataLoader guarantee the result order matches the input key order?
  • How would you handle the N+1 problem across multiple levels of nested resolvers?
  • What is the difference between DataLoader's per-request cache and a longer-lived cache?
  • How would you detect an N+1 problem in production without manually reading resolver code?

MCQ Practice

1. What causes the GraphQL N+1 problem by default?

Each resolver call for a nested field fires its own lookup unless something batches them together.

2. What is the standard tool used to solve the N+1 problem in GraphQL?

DataLoader collects individual key lookups during one tick and resolves them with one batched query.

3. For a query returning 50 posts each needing an author lookup, how many queries does a naive resolver issue?

One query for the 50 posts plus one separate query per post for its author equals 51 total.

Flash Cards

What is the GraphQL N+1 problem?One query for a list plus one extra query per item for a nested field.

Why does it happen by default?Field-level resolvers run independently, unaware of sibling requests in the same tick.

Standard fix?DataLoader — batches and deduplicates per-item lookups into one combined query.

50 posts + author each, naive query count?51 (1 list query + 50 per-post author queries).

1 / 4

Continue Learning