What Is a Resolver Function?
A resolver is simply a function attached to a single field in your GraphQL schema whose job is to return the value for that field. When the GraphQL server executes an incoming query, it walks the selection set field by field and calls the matching resolver for each one, collecting the returned values into the final response shape. Unlike REST, where one handler builds an entire response, GraphQL spreads responsibility across many small, focused functions, one per field.
Cricket analogy: Think of a resolver like a fielder assigned to a specific position: the third slip only worries about catching edges near him, not what happens at fine leg, just as a resolver only worries about producing its own field's value.
The Resolver Signature: parent, args, context, info
Every resolver in a JavaScript GraphQL server (using graphql-js or Apollo Server) receives four positional arguments: parent (the result returned by the resolver of the parent field, often called root or obj), args (an object of the arguments supplied in the query for this field), context (a shared object built once per request, typically holding the authenticated user, database connections, or dataloaders), and info (an object describing the execution state, including the AST and schema details, rarely used directly in application code).
Cricket analogy: The parent argument is like the score handed down from the previous over: a bowler's next over is shaped by what already happened, just as a resolver's parent value is shaped by the field above it in the tree.
const resolvers = {
Query: {
book: (parent, args, context, info) => {
// args.id comes from the query: book(id: "42") { title }
return context.dataSources.books.findById(args.id);
},
},
Book: {
// parent is the Book object returned above
title: (parent) => parent.title,
author: (parent, args, context) => {
return context.dataSources.authors.findById(parent.authorId);
},
},
};Default Resolvers and Property Shorthand
You do not need to write a resolver for every single field. If a field is omitted from the resolver map, GraphQL.js falls back to a default resolver that simply reads a same-named property off the parent object, meaning title: parent.title happens automatically if parent already has a title property. This default behavior is why many scalar fields on ORM-backed types never need an explicit resolver: the object returned by the parent's resolver already carries matching keys.
Cricket analogy: A batter who plays a textbook forward defensive without thinking through every biomechanical detail is relying on ingrained muscle memory, the way a default resolver relies on the property already being there.
You only need a custom resolver when the field name differs from the parent property, when a computation is required, or when the value must be fetched from another data source (database, REST API, or another service).
Synchronous vs Asynchronous Resolvers
A resolver can return a plain value, or it can return a Promise, and GraphQL.js automatically awaits it before continuing. This is essential because most real resolvers fetch data from a database or an upstream API, operations that are inherently asynchronous. GraphQL executes sibling fields concurrently where possible: if title and author both need async work, their promises are kicked off together rather than sequentially, which keeps overall query latency close to the slowest single resolver rather than the sum of all of them.
Cricket analogy: Two physios treating different injured players in the dressing room at the same time, rather than one after another, finish faster together, just as concurrent resolver promises finish faster than sequential ones.
If a resolver throws an error or its returned promise rejects, GraphQL does not fail the entire response by default. It sets that field to null in the data, adds an entry to the top-level errors array, and continues resolving the sibling fields, unless the field is marked non-nullable, in which case the null propagates upward.
- A resolver is a function bound to one schema field that returns that field's value.
- Resolvers receive four arguments: parent, args, context, and info.
- parent is the value returned by the resolver of the enclosing field.
- context is a per-request shared object used for auth, database clients, and dataloaders.
- Fields without an explicit resolver fall back to reading a same-named property off parent.
- Resolvers can return promises, and GraphQL.js awaits them, running sibling fields concurrently.
- A rejected or throwing resolver nulls out that field and records an error without crashing the whole query, unless the field is non-nullable.
Practice what you learned
1. What is the primary responsibility of a single GraphQL resolver function?
2. In the resolver signature (parent, args, context, info), what does 'parent' represent?
3. What happens when a field in the resolver map is omitted entirely?
4. How does GraphQL.js handle a resolver that returns a Promise?
5. What happens to the response if a nullable field's resolver throws an error?
Was this page helpful?
You May Also Like
The Resolver Chain and Context
Understand how resolvers link together into a chain across the query tree and how the shared context object flows through that chain.
Resolving Nested Fields
See how GraphQL resolves deeply nested object fields, including lists of objects, and why field resolution order matters for performance.
Error Handling in Resolvers
Learn how GraphQL's partial-response error model works, how nullability affects error propagation, and how to design custom, informative errors.
DataLoader and the N+1 Problem
Understand why naive GraphQL resolvers trigger the N+1 query problem and how Facebook's DataLoader batches and caches requests to fix it.
Related Reading
Related Study Notes in Web Development
Browse all study notesWebSockets Study Notes
Web Development · 30 topics
Web DevelopmentWebAssembly Study Notes
WebAssembly · 30 topics
Web DevelopmentgRPC Study Notes
Protocol Buffers · 30 topics
Web DevelopmentSpring Boot Study Notes
Java · 30 topics
Web DevelopmentFlask Study Notes
Python · 30 topics
Web DevelopmentDjango Study Notes
Python · 30 topics