Overview
Designs complete, production-ready GraphQL schemas including type definitions (scalar, object, input, enum, interface, union), queries, mutations, subscriptions, resolver patterns, solutions to the N+1 problem (DataLoader), pagination (cursor-based), error handling via union types or extensions, and guidance on schema-first vs code-first, stitching vs federation.
When to Use This Skill
- Building a new GraphQL API or refactoring an existing one.
- User describes data model or operations ("users can query their orders with line items and status history").
- Choosing between REST and GraphQL or improving an existing GraphQL schema.
Prerequisites
- GraphQL server (Apollo Server, Yoga, Pothos, Nexus, or codegen-based).
- Database or data sources the resolvers will call.
- For advanced: DataLoader, Redis for caching, understanding of federation.
Steps
Schema-first vs code-first decision:
- Schema-first: SDL + resolvers (good for collaboration with frontend).
- Code-first: TypeScript classes/decorators or builder (better DX, type safety).
Core type system:
- Scalars (ID, String, Int, Float, Boolean, custom DateTime, JSON).
- Enums for status fields.
- Input types for mutations.
- Interfaces and unions for polymorphism.
Query design:
- Root queries should be specific (not generic "node" unless using Relay).
- Always think about what the client actually needs (avoid over-fetching by design).
N+1 problem & DataLoader:
- Identify batchable loads (e.g., user for each post).
- Create DataLoader per type.
- Use in resolvers:
loader.load(id).
Pagination:
- Prefer cursor-based (Relay connection spec or simple
after + first).
- Provide
edges + pageInfo or a simpler items + hasMore.
- Offset pagination only for admin/internal use cases.
Mutations & input validation:
- One mutation per action.
- Return the mutated entity or a payload type.
- Use input objects.
Error handling:
- Use union error types (e.g.,
CreatePostResult = Post | ValidationError | Unauthorized).
- Or GraphQL errors with extensions.
Subscriptions (real-time):
- Use
graphql-ws or Apollo subscriptions.
- Pub/sub backend (Redis, in-memory for dev).
Output:
- Complete SDL or code-first schema.
- Resolver map or class.
- DataLoader setup example.
- Pagination helper.
- Example queries/mutations in the response.
Examples
Full schema for a blog + comments + users (with DataLoader, cursor pagination, and union error types) is provided, along with resolver skeleton and subscription example.
Edge Cases & Error Handling
- Circular references: Use lazy loading or interfaces.
- Authorization: Perform auth checks inside resolvers or with middleware/directives.
- Rate limiting & complexity: Use graphql-query-complexity or persisted queries.
- Schema evolution: Deprecate fields instead of removing; use versioning or federation for major changes.
Verification
- Load the schema in GraphQL Playground / Apollo Studio / Insomnia.
- Run example queries and mutations — they return expected shapes.
- Enable DataLoader batching and confirm single DB query for lists.
- Test pagination cursors with real data.
- Subscriptions fire on mutation.
- Success: Schema is expressive, performant (no N+1), type-safe on both sides, and easy to evolve.
References
1---2name: graphql-schema-designer3description: Designs GraphQL schemas with types, queries, mutations, subscriptions, and resolvers. Use when building or refactoring a GraphQL API.4license: Apache-2.05---67## Overview89Designs complete, production-ready GraphQL schemas including type definitions (scalar, object, input, enum, interface, union), queries, mutations, subscriptions, resolver patterns, solutions to the N+1 problem (DataLoader), pagination (cursor-based), error handling via union types or extensions, and guidance on schema-first vs code-first, stitching vs federation.1011## When to Use This Skill1213- Building a new GraphQL API or refactoring an existing one.14- User describes data model or operations ("users can query their orders with line items and status history").15- Choosing between REST and GraphQL or improving an existing GraphQL schema.1617## Prerequisites1819- GraphQL server (Apollo Server, Yoga, Pothos, Nexus, or codegen-based).20- Database or data sources the resolvers will call.21- For advanced: DataLoader, Redis for caching, understanding of federation.2223## Steps24251. **Schema-first vs code-first decision**:26 - Schema-first: SDL + resolvers (good for collaboration with frontend).27 - Code-first: TypeScript classes/decorators or builder (better DX, type safety).28292. **Core type system**:30 - Scalars (ID, String, Int, Float, Boolean, custom DateTime, JSON).31 - Enums for status fields.32 - Input types for mutations.33 - Interfaces and unions for polymorphism.34353. **Query design**:36 - Root queries should be specific (not generic "node" unless using Relay).37 - Always think about what the client actually needs (avoid over-fetching by design).38394. **N+1 problem & DataLoader**:40 - Identify batchable loads (e.g., user for each post).41 - Create DataLoader per type.42 - Use in resolvers: `loader.load(id)`.43445. **Pagination**:45 - Prefer cursor-based (Relay connection spec or simple `after` + `first`).46 - Provide `edges` + `pageInfo` or a simpler `items` + `hasMore`.47 - Offset pagination only for admin/internal use cases.48496. **Mutations & input validation**:50 - One mutation per action.51 - Return the mutated entity or a payload type.52 - Use input objects.53547. **Error handling**:55 - Use union error types (e.g., `CreatePostResult = Post | ValidationError | Unauthorized`).56 - Or GraphQL errors with extensions.57588. **Subscriptions** (real-time):59 - Use `graphql-ws` or Apollo subscriptions.60 - Pub/sub backend (Redis, in-memory for dev).61629. **Output**:63 - Complete SDL or code-first schema.64 - Resolver map or class.65 - DataLoader setup example.66 - Pagination helper.67 - Example queries/mutations in the response.6869## Examples7071Full schema for a blog + comments + users (with DataLoader, cursor pagination, and union error types) is provided, along with resolver skeleton and subscription example.7273## Edge Cases & Error Handling7475- **Circular references**: Use lazy loading or interfaces.76- **Authorization**: Perform auth checks inside resolvers or with middleware/directives.77- **Rate limiting & complexity**: Use graphql-query-complexity or persisted queries.78- **Schema evolution**: Deprecate fields instead of removing; use versioning or federation for major changes.7980## Verification81821. Load the schema in GraphQL Playground / Apollo Studio / Insomnia.832. Run example queries and mutations — they return expected shapes.843. Enable DataLoader batching and confirm single DB query for lists.854. Test pagination cursors with real data.865. Subscriptions fire on mutation.876. Success: Schema is expressive, performant (no N+1), type-safe on both sides, and easy to evolve.8889## References9091- [GraphQL.js](https://graphql.org/graphql-js/)92- [Apollo Server](https://www.apollographql.com/docs/apollo-server/)93- [Relay Cursor Connections Spec](https://relay.dev/graphql/connections.htm)94- [DataLoader](https://github.com/graphql/dataloader)95- [Pothos GraphQL](https://pothos-graphql.dev/) or [Nexus](https://nexusjs.org/)96- [GraphQL Error Best Practices](https://www.apollographql.com/docs/apollo-server/data/errors/)