DM
Technical reference

GraphQL Cheatsheet

Typed APIs with client-selected data

Must Know

Query

Ask for exactly the fields the client needs.

query User($id: ID!) {
  user(id: $id) { id name posts { id title } }
}

Schema

Nullability is part of the public API contract.

type User { id: ID!, name: String!, posts: [Post!]! }
type Query { user(id: ID!): User }

Important Patterns

Mutation

mutation UpdateUser($input: UpdateUserInput!) {
  updateUser(input: $input) { user { id name } errors { field message } }
}
javascript

Resolver Authorization

Authorize inside resolvers, not only in the UI.

const user = requireUser(context);
const post = await db.post.findUnique({ where: { id } });
if (post.authorId !== user.id) throw new ForbiddenError();

Useful Recipes

Reusable Fragment

fragment UserCard on User { id name avatarUrl }

query Team { team { members { ...UserCard } } }

Cursor Pagination

Cursor pagination behaves better than offsets on changing data.

type PageInfo { endCursor: String, hasNextPage: Boolean! }
type PostConnection { edges: [PostEdge!]!, pageInfo: PageInfo! }

Pitfalls & Production

javascript

Prevent N+1

Batch and cache related entity loads per request.

const userLoader = new DataLoader(ids => db.user.findMany({ where: { id: { in: ids } } }));

Protect the API

A single GraphQL endpoint still needs resource controls.

depth limit
query complexity budget
request timeout
persisted queries
rate limits