Web Development7 min read

GraphQL

Query language and runtime for APIs - clients request exactly the fields they need, one endpoint replaces many REST routes, strong schema typing catches errors at build time.

GraphQLAPIApolloSchemaType System

skill: GraphQL category: Web Development tags: [GraphQL, API, Apollo, Schema, Type System] readingTime: 7

GraphQL is ideal when clients have diverse data needs, you have many frontend teams consuming the same API, or you need real-time subscriptions. For simple CRUD APIs with a single client, REST is simpler. For very high-throughput simple queries, REST may outperform due to fewer resolver overheads.

Workflow

  1. Define the schema firstSchema-first development makes the contract explicit - frontend and backend teams agree on types before writing any resolver logic.
  2. Set up Apollo ServerApollo Server handles parsing, validation, execution, and error formatting - letting you focus on resolver logic.
  3. Write resolversResolvers map schema fields to data sources - DB queries, REST calls, or computed values.
  4. Solve the N+1 problem with DataLoaderWithout batching, fetching 100 posts each calling user resolver fires 100 DB queries. DataLoader batches them into one.
  5. Add subscriptions for real-timeGraphQL subscriptions push data changes to clients over WebSockets - no polling required.

Output Format

GraphQL API with typed schema, resolvers, DataLoader batching, and Apollo Server.

graphql-api/
├── schema.graphql      # Type definitions
├── resolvers/
│   ├── query.ts
│   ├── mutation.ts
│   └── subscription.ts
├── dataloaders/        # Batching per entity
├── context.ts          # DB, auth, loaders
└── server.ts

Examples

Input

Output

Input

Output

Edge Cases & Gotchas

  • N+1 without DataLoader - Every resolver that fetches a related entity without batching multiplies DB queries. Always use DataLoader for any one-to-many or many-to-one resolver.
  • Introspection in production - GraphQL introspection exposes your full schema. Disable it in production unless you're building a public API: `introspection: process.env.NODE_ENV !== 'production'`.
  • Large query depth attacks - Deeply nested queries can DOS your server. Use `graphql-depth-limit` or `graphql-query-complexity` to reject expensive queries.
  • Nullable vs non-null types - Non-null fields (!) propagate errors upward - a resolver error on a non-null field nulls the entire parent. Mark fields nullable unless you're certain they'll always resolve.

When to Break These Rules

  • Use REST for simple CRUD APIs with one client - GraphQL's overhead (schema, resolvers, DataLoader) isn't worth it for three endpoints.
  • Use gRPC when you need binary efficiency, streaming, or server-to-server communication without a browser client.

Reference Files

  • https://graphql.org/learn/
  • https://www.apollographql.com/docs/apollo-server

More skills in this library

Browse all technical skills - Mobile, AI/ML, Web, Backend, Design, and Product.