Resolvers: Turning Queries into Data
What a resolver is
The schema says what is available; resolvers say how to fetch it. A resolver is a function attached to a field that returns that field's value – from a database, another API, or memory.
A resolver map (JavaScript)
const resolvers = {
Query: {
user: (parent, args) => db.users.find(args.id),
posts: () => db.posts.all(),
},
User: {
posts: (user) => db.posts.byAuthor(user.id),
},
};
Each resolver receives the parent object, the args passed to the field, and a shared context (holding things like the logged-in user and database handles).
Resolving a query tree
GraphQL executes a query by walking its tree, calling a resolver for each field. For user(id:1) { posts { title } }:
Query.userruns, returning a user.- That user becomes the parent for
User.posts, which fetches the posts. - Each post resolves its
title(often just reading a field).
You only write resolvers where the default (read the field off the parent object) is not enough.
The N+1 problem
Walking the tree naively can fire one query per item – fetch 10 users, then 10 separate queries for their posts. This is the classic N+1 problem. The standard fix is a DataLoader, which batches and caches those lookups into a single query per level.
Key points
- Resolvers are functions that fetch the value for a schema field.
- Each receives the parent object, field arguments and a shared context.
- GraphQL walks the query tree, resolving fields top-down.
- Batch lookups with a DataLoader to avoid the N+1 query problem.