GraphQL Cheat Sheet
Complete GraphQL reference covering SDL schema types, queries, mutations, subscriptions, resolvers, DataLoader, Apollo Client, pagination patterns, and performance best practices.
📚 Quick Navigation
What is GraphQL?
GraphQL is a query language for APIs and a runtime for executing those queries developed by Facebook (now Meta) in 2012 and open-sourced in 2015. Unlike REST, where each endpoint returns a fixed data structure, GraphQL allows clients to request exactly the fields they need — no more, no less — in a single request.
The core idea is a strongly-typed schema that serves as a contract between client and server. Every piece of data your API can return is described in the schema using the Schema Definition Language (SDL). This schema drives auto-documentation, validation, and tooling like GraphiQL and Apollo Studio.
Key Features
- ▸Declarative data fetching — clients specify the exact shape of data needed
- ▸Single endpoint — all operations go through one URL (typically /graphql)
- ▸Strongly typed schema — every field has a declared type; queries are validated before execution
- ▸Introspection — clients can query the schema itself to discover available types and operations
- ▸Real-time with subscriptions — WebSocket-based live updates built into the spec
When to Use GraphQL
- ✓Multiple clients (web, mobile) consuming the same API with different data needs
- ✓Rapidly evolving product where frontend needs frequently change
- ✓Aggregating data from multiple microservices or databases
- ✓Applications requiring real-time data with subscriptions
- ✗Simple CRUD APIs with few clients — REST may be simpler and faster to build
GraphQL vs REST
| Aspect | GraphQL | REST |
|---|---|---|
| Endpoints | Single /graphql | Multiple per resource |
| Over/Under-fetching | Eliminated by design | Common problem |
| Versioning | Schema evolution (add fields, deprecate) | /v1, /v2 URL versioning |
| Caching | Client-side (normalized) or APQ | HTTP cache (CDN-friendly) |
| Learning Curve | Higher (SDL, resolvers, N+1) | Lower (HTTP + JSON) |
GraphQL Tips & Best Practices
Use DataLoader for every relationship
Any field that resolves a related type (e.g., Post.author) will cause N+1 queries without DataLoader.
Always validate in mutations
Throw GraphQLError with code: BAD_USER_INPUT for validation errors so clients can display them properly.
Name all operations
Named operations appear in Apollo Studio traces and error logs. Anonymous queries are much harder to debug in production.
Co-locate fragments with components
Define the fragment a component needs next to that component (Apollo Client supports this). Prevents over-fetching at the component level.
Limit query depth and complexity
Without depth limits, a malicious client can craft a deeply nested query that recursively loads millions of DB rows.
Never expose raw DB errors
Use formatError to sanitize errors in production. Stack traces and DB error messages reveal sensitive implementation details.
Use cursor pagination for large datasets
Offset pagination breaks when items are added or deleted between pages. Cursor-based pagination (Relay spec) stays consistent.
Prefer the union error pattern
Returning union types from mutations (Success | Error) is type-safe and explicit compared to throwing errors that break partial responses.