Stop 09 · API DesignTopics · 7/12

GraphQL Schema & Resolvers

Part of the Backend Developer Roadmap

In short

A GraphQL server has two halves. The schema is the menu of what clients can ask for. Resolvers are the cooks who fetch each item. Get both right and the API nearly documents itself.

The schema defines your API's types and operations; resolvers are the functions that actually fetch the data for each field — together they form a working GraphQL API.

The blob character in a chef's hat holds a menu while three cooks each stir a pot.

Think of it like this

The wedding caterer's menu and cooks

The caterer gives guests a menu card: these dishes, nothing else. Behind the curtain, each cook owns one dish. A guest orders three, and only those three cooks get busy. The schema is the menu card. Each resolver is the cook for one field.

Watch it happen

Resolving book(id: 1) { title author { name } }

Query.book
Book.title
Book.author
Author.name

1/4The Query.book resolver runs first and loads book 1 from the database.

The big ideas

What you need to know

The schema is the contract

Written in SDL: types, fields and their types. Clients can only ask for what's declared.

A resolver per field

Each field can have a function (parent, args, context) that returns its value. Plain fields use a default.

Resolvers run as a tree

Parents resolve first and pass their result down. That's how nested data comes together.

Watch for N+1

Listing 50 books that each fetch their author means 51 queries. DataLoader batches them into two.

See it in code

Walk through the code

ts
1import { ApolloServer } from "@apollo/server";2import { startStandaloneServer } from "@apollo/server/standalone";3 4const typeDefs = `#graphql5  type Author { id: ID!, name: String! }6  type Book { id: ID!, title: String!, author: Author! }7  type Query { book(id: ID!): Book }8`;9 10const resolvers = {11  Query: { book: (_: unknown, { id }: { id: string }) => db.books.find(id) },12  Book: { author: (book: { authorId: string }) => db.authors.find(book.authorId) },13};14 15const server = new ApolloServer({ typeDefs, resolvers });16await startStandaloneServer(server, { listen: { port: 4000 } });

1/3The schema in SDL. The ! means non-null. Query.book is the only entry point.

db is your data layer. Open http://localhost:4000 to try queries in Apollo's built-in sandbox.

Save yourself the pain

Common mistakes

Oops

Writing a resolver for every single field, even plain ones.

Do this instead

Fields like title already resolve by reading parent.title. Only write resolvers for fields that need extra work.

Oops

Fetching each book's author with its own query in a list.

Do this instead

Use DataLoader to batch those lookups into one WHERE id IN (...) query per request.

Your mission

Add a reviews field

~30 min

Quick check

In the resolver Book.author(book), what is the book argument?

Go deeper

  1. 1Define types, queries and mutations in a GraphQL schema.
  2. 2Write resolvers that fetch data from a database for each field.
  3. 3Learn the N+1 query problem in GraphQL and how DataLoader solves it.

More topics at this stop

Stuck on this topic? Ask an Insider

Get 1:1 guidance from people who've walked this exact path — on the InsideEdge app.

Download
InsideEdge