Apollo Server is the most popular way to build a GraphQL API with Node.js. It handles parsing queries, validating against your schema, running resolvers, and formatting responses.
Setup
mkdir graphql-api && cd graphql-api
npm init -y
npm install @apollo/server graphqlYour First Server
Run it: node --experimental-vm-modules index.js
Resolvers in Detail
Every field in your schema has a resolver function with this signature:
fieldName(parent, args, context, info) { ... }| Argument | What it contains |
|---|---|
parent | The resolved value of the parent object |
args | Arguments passed to this field in the query |
context | Shared data (auth user, database connection) |
info | Query AST and execution metadata |
Context — Sharing Auth Across Resolvers
Pass shared data like the authenticated user through context:
Testing with GraphiQL
Apollo Server ships a built-in browser IDE at http://localhost:4000. You can write queries, run them, and explore the schema — no extra tooling needed during development.
Try running these against the server above:
query AllBooks {
books {
id
title
author
year
}
}
mutation AddBook {
addBook(title: "Refactoring", author: "Martin Fowler", year: 2018) {
id
title
}
}Schema-First vs Code-First
| Approach | Description | Tooling |
|---|---|---|
| Schema-first | Write SDL (.graphql files), generate resolvers | Apollo Server, graphql-tools |
| Code-first | Define schema in code, SDL auto-generated | TypeGraphQL, Pothos |
Schema-first (what we've used here) is more explicit and makes the SDL the source of truth. Code-first is preferred in TypeScript projects where you want type safety across schema and resolvers.
Error Handling
Throw GraphQLError for user-facing errors with proper error codes: