Setting Up a GraphQL Server
Standing up a minimal GraphQL server takes four concrete steps regardless of language or framework: install a server library (Apollo Server for Node.js is the most common starting point), write your typeDefs — the schema in SDL — describing the types and operations you'll support, write resolvers that implement how each field's data is actually fetched, and finally instantiate and start the server so it listens for incoming HTTP requests, typically on a single /graphql (or root) path. Apollo Server's startStandaloneServer helper wraps this into just a few lines, making it realistic to have a working, introspectable GraphQL API running locally in under five minutes.
Cricket analogy: Setting up a GraphQL server is like preparing a new cricket ground for its first match: mark the pitch dimensions (typeDefs), assign umpires to specific decisions (resolvers), then officially open the gates (start the server) so play can begin.
Defining typeDefs and Resolvers
typeDefs are typically written using the gql template literal tag, which is just a string of SDL that Apollo Server parses into an internal schema representation, for example a Query type exposing a books field that returns a list of Book objects. Resolvers are written as a plain JavaScript (or TypeScript) object whose shape mirrors the schema: a Query key containing a books function, and, if Book has a nested author field pointing to another type, a separate Book key containing an author function — the resolver map's structure literally follows the schema's type and field names, so Apollo Server knows exactly which function to call for which field.
Cricket analogy: The resolver map mirroring the schema's shape is like a scorecard app's function for 'battingAverage' living directly under the 'Batter' section, matching exactly where that stat appears on the printed scorecard.
import { ApolloServer } from '@apollo/server';
import { startStandaloneServer } from '@apollo/server/standalone';
const typeDefs = `#graphql
type Book {
title: String
author: String
}
type Query {
books: [Book]
}
`;
const books = [
{ title: 'The Hobbit', author: 'J.R.R. Tolkien' },
{ title: 'Dune', author: 'Frank Herbert' },
];
const resolvers = {
Query: {
books: () => books,
},
};
const server = new ApolloServer({ typeDefs, resolvers });
const { url } = await startStandaloneServer(server, {
listen: { port: 4000 },
});
console.log(`Server ready at ${url}`);The Resolver Signature: parent, args, context, info
Every resolver function receives four positional arguments: parent (sometimes called root), which is the result already returned by the resolver for the parent field, letting nested resolvers use data already fetched one level up; args, an object containing any arguments passed to the field in the query, such as { id: '42' } for a book(id: "42") query; context, a shared object created once per incoming request and passed to every resolver in that request's execution, commonly used to carry an authenticated user, a database connection, or a DataLoader instance; and info, which contains lower-level details about the execution state and the query's AST, rarely needed outside of advanced use cases like dynamic field selection optimization.
Cricket analogy: The parent argument is like a bowling-figures resolver already knowing which bowler it's calculating for, because that bowler was already selected one level up by the innings resolver.
The context object is created fresh once per incoming request (usually inside the server's context function) and is the standard place to attach an authenticated user, a database connection pool, or per-request DataLoader instances, since it's automatically threaded through to every resolver that executes during that request.
Testing and Iterating with Apollo Sandbox
Apollo Server ships with Apollo Sandbox, a browser-based IDE served at the same endpoint that provides autocomplete, inline documentation generated from the schema's descriptions, and a query history, all powered by GraphQL's introspection system, which lets any client ask the schema what types and fields it exposes. During local development this makes iterating fast: you can write a query, immediately see type errors if a field doesn't exist, and test a mutation's effects before wiring up any frontend code, since the sandbox sends real requests to your running resolvers exactly as a production client would.
Cricket analogy: Apollo Sandbox is like a practice net session before the real match: a bowler tests deliveries against a stand-in batter to see what works before facing live opposition in an actual game.
Never ship a GraphQL server to production with the same defaults as local development: disable or authenticate access to Apollo Sandbox/introspection for public APIs, add query depth or complexity limiting to prevent malicious deeply-nested queries, configure CORS explicitly, and make sure detailed error messages and stack traces aren't leaked to clients.
- A minimal GraphQL server needs four steps: install a library, write typeDefs, write resolvers, and start the server.
- typeDefs are SDL, commonly written with the gql tag; resolvers are a plain object whose shape mirrors the schema's types and fields.
- Every resolver receives four arguments: parent, args, context, and info.
- context is created once per request and is the standard place to share an authenticated user, DB connection, or DataLoader.
- Apollo Sandbox provides an introspection-powered browser IDE for autocomplete, docs, and fast local query testing.
- Production deployments need introspection/sandbox access control, query complexity limits, explicit CORS config, and safe error handling.
Practice what you learned
1. What are the four basic steps to stand up a minimal GraphQL server?
2. What does the resolver map's object structure correspond to?
3. Which resolver argument is a shared object created once per incoming request, commonly used for authentication or a database connection?
4. What powers Apollo Sandbox's autocomplete and inline documentation?
5. Which of the following is a recommended production hardening step for a GraphQL server?
Was this page helpful?
You May Also Like
The GraphQL Schema
How GraphQL's Schema Definition Language describes types, fields, and operations as the contract between client and server.
Scalar and Object Types
A deep dive into GraphQL's built-in scalar types, custom scalars, enums, and how object types compose the graph.
What Is GraphQL?
An introduction to GraphQL as a query language and runtime for APIs, and the problems it was designed to solve.
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