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

KindUse
typeObject type
inputMutation input shape
enumFixed value set
interfaceShared fields
unionOne-of types
scalarCustom 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

Example: Mutation

mutation CreateUser($email: String!) {
  createUser(email: $email) { id email }
}

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));
    })
  };
}