Build the mental model
When a list query returns N tutorials and each one's `author` field resolver fires its own separate database query, you get one list query plus N author queries — N+1 total — and the load grows with result count. DataLoader batches field-resolver calls within one event-loop tick during a request, issues a single database call for the unique keys (`WHERE id IN (...)`), and caches results for the rest of that request.
Connect it to a real scenario
Rendering the Tutorial Platform homepage's 20-tutorial list with author names used to fire 20 separate author queries with a naive resolver, but wiring an `authorLoader` into the context collapses that to one author query. A loader instance must be created fresh per request — never shared across requests, to avoid stale or leaked caches.
Try the working example
const authorLoader = new DataLoader(async (authorIds) => {
const authors = await db.author.findMany({
where: { id: { in: authorIds } },
});
const byId = new Map(authors.map((author) => [author.id, author]));
return authorIds.map((id) => byId.get(id) ?? null);
});
const resolvers = {
Tutorial: {
author: (tutorial, _args, context) =>
context.loaders.author.load(tutorial.authorId),
},
};You can identify an N+1 problem and write a batching resolver with DataLoader.5-minute try-it
Design a `commentsByTutorialLoader` for the `Tutorial.comments` field and describe the batch function's return-order requirement (it must match the input keys' order).
One important caution
Returning results out of order from a DataLoader batch function silently matches the wrong author to the wrong tutorial — always preserve order with a `keys.map(...)` pattern.
Apollo Server — Batching with DataLoader — GraphQL