GraphQL What Are Resolvers
A resolver is a function on the server that provides the value for a single field in your schema. Every field in a GraphQL schema has a resolver. When a client requests a field, GraphQL calls that field's resolver to get the data. Resolvers are where your schema connects to the real world — databases, REST APIs, files, and anything else.
One Field, One Resolver
Schema field Resolver function ──────────── ───────────────── Query.user ──► () => db.findUser() User.name ──► (user) => user.name User.posts ──► (user) => db.findPostsByUser(user.id) Post.title ──► (post) => post.title
The Resolver Waterfall
GraphQL executes resolvers in a top-down cascade. The root resolver runs first and returns a parent object. Then each child field's resolver receives that parent object and returns its own value.
Query: { user(id:"1") { name posts { title } } }
Step 1: Query.user resolver runs
→ Returns user object { id:"1", name:"Sam", ... }
Step 2: User.name resolver runs with parent = user object
→ Returns "Sam"
Step 3: User.posts resolver runs with parent = user object
→ Returns [{ id:"p1", title:"Hello" }, ...]
Step 4: Post.title resolver runs for each post
→ Returns "Hello" for post p1
Resolver Function Signature
Every resolver receives four arguments, always in this order:
function fieldResolver(parent, args, context, info) {
// parent → The object returned by the parent resolver
// args → Arguments passed by the client in the query
// context → Shared data: database, auth token, logger
// info → Technical details about the query (rarely used)
}
A Concrete Example
Schema:
────────
type Query {
book(id: ID!): Book
}
type Book {
id: ID!
title: String!
author: String!
}
Resolvers:
───────────
const books = [
{ id: "1", title: "Dune", author: "Frank Herbert" },
{ id: "2", title: "Foundation", author: "Isaac Asimov" },
];
const resolvers = {
Query: {
book: (parent, args, context) => {
return books.find(b => b.id === args.id);
// ↑ args.id comes from book(id: "1")
}
},
Book: {
title: (parent) => parent.title, ← parent is the book object
author: (parent) => parent.author,
}
};
Default Resolvers Save You Work
GraphQL provides a built-in default resolver for any field you do not define yourself. The default resolver reads the property with the same name from the parent object. This is why the Book.title and Book.author resolvers in the example above are optional — GraphQL would handle them automatically.
Default resolver behavior: ─────────────────────────── Field: title Default resolver: (parent) => parent["title"] As long as the parent object has a "title" property, you do not need to write a resolver for it.
When You Must Write a Custom Resolver
Situation Example ───────── ─────── Field name differs from DB column schema: fullName, DB: full_name Field needs a DB query user.posts → SELECT * FROM posts WHERE user_id=? Field combines multiple data sources user.weather → city + weather API call Field transforms data price in cents → price in dollars Field applies business logic user.isAdmin → check roles table
Key Points
- Every schema field has a resolver function that provides its value.
- Resolvers receive four arguments: parent, args, context, and info.
- Resolvers run in a top-down cascade — the parent resolver's return value becomes the parent argument of child resolvers.
- GraphQL provides default resolvers that read same-name properties from the parent object automatically.
- Write custom resolvers when data needs a database query, transformation, or combination of sources.
