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