Implementing GraphQL
1. Installing express-graphql
Example: Install (modern)
# 2026: prefer Apollo Server v4 or graphql-yoga over the deprecated express-graphql
npm i @apollo/server @as-integrations/express5 graphql
# or:
npm i graphql-yoga graphql
Warning:
express-graphql is deprecated. Use @apollo/server or graphql-yoga for new projects.2. Creating GraphQL Schema
Example: SDL
type User { id: ID!, email: String!, posts: [Post!]! }
type Post { id: ID!, title: String!, author: User! }
type Query {
user(id: ID!): User
users(limit: Int = 20): [User!]!
}
type Mutation {
createUser(email: String!): User!
}
3. Defining Types
| Kind | Use |
|---|---|
| type | Object type |
| input | Mutation input shape |
| enum | Fixed value set |
| interface | Shared fields |
| union | One-of types |
| scalar | Custom types (DateTime, JSON) |
4. Creating Resolvers
Example: Resolvers
const resolvers = {
Query: {
user: (_p, { id }) => db.users.findById(id),
users: (_p, { limit }) => db.users.list({ take: limit })
},
Mutation: {
createUser: (_p, { email }, { user }) => {
if (!user) throw new GraphQLError("Unauthorized", { extensions: { code: "UNAUTHENTICATED" } });
return db.users.create({ email });
}
},
User: {
posts: (parent, _a, { loaders }) => loaders.postsByAuthor.load(parent.id)
}
};
5. Setting Up GraphQL Endpoint
Example: Apollo + Express 5
import { ApolloServer } from "@apollo/server";
import { expressMiddleware } from "@as-integrations/express5";
const apollo = new ApolloServer({ typeDefs, resolvers });
await apollo.start();
app.use("/graphql", express.json(), expressMiddleware(apollo, {
context: async ({ req }) => ({ user: req.user, loaders: makeLoaders() })
}));
6. Using graphqlHTTP Middleware
Example: graphql-yoga
import { createYoga } from "graphql-yoga";
const yoga = createYoga({ schema, context: ({ request }) => ({ user: request.user }) });
app.use(yoga.graphqlEndpoint, yoga);
7. Enabling GraphiQL Interface
Example: Apollo Sandbox / Yoga GraphiQL
// Apollo: Sandbox is on by default in dev when introspection is enabled
new ApolloServer({ typeDefs, resolvers, introspection: process.env.NODE_ENV !== "production" });
// Yoga: GraphiQL enabled by default at /graphql
Note: Disable introspection and the playground in production to reduce attack surface.
8. Handling Queries
Example: Curl query
curl -X POST http://localhost:3000/graphql \
-H "Content-Type: application/json" \
-d '{"query":"{ user(id:\"1\"){ email } }"}'
9. Handling Mutations
10. Implementing Authentication
Example: Context-based auth
function requireUser(ctx) {
if (!ctx.user) throw new GraphQLError("Unauthorized", { extensions: { code: "UNAUTHENTICATED" } });
return ctx.user;
}
const resolvers = {
Query: { me: (_p, _a, ctx) => requireUser(ctx) }
};
11. Using DataLoader for Batching
Example: Batch + cache N+1
import DataLoader from "dataloader";
export function makeLoaders() {
return {
postsByAuthor: new DataLoader(async (authorIds) => {
const rows = await db.posts.findMany({ where: { authorId: { in: authorIds } } });
const byAuthor = new Map(authorIds.map(id => [id, []]));
for (const p of rows) byAuthor.get(p.authorId).push(p);
return authorIds.map(id => byAuthor.get(id));
})
};
}