GraphQL API Design
Purpose
Evaluate GraphQL against the project's needs and, if chosen, design the schema, resolver strategy, N+1 protection, pagination, and security limits — as a contract, not code.
When to Use
- When clients need flexible, nested data selection (multiple frontends with divergent data needs).
- Not when a straightforward REST surface serves the clients — evaluate first, don't assume.
Inputs
- Domain model, client list and their data-shape needs.
- Auth model (
backend-authentication, backend-authorization).
Discovery Questions
- Do clients genuinely need flexible selection/nesting, or would a few REST endpoints do?
- What are the deepest/heaviest queries clients will run?
- Who may introspect the schema in production?
Responsibilities
- Fit decision first: GraphQL earns its complexity with multiple clients needing different shapes of the same graph; otherwise recommend REST (
rest-api-design).
- Design the schema from the domain graph, not the database tables; nullable vs non-null deliberately.
- Plan resolver data loading with dataloaders/batching — N+1 is the default failure, design against it explicitly.
- Use connection-style pagination for lists; no unbounded list fields.
- Design mutations with typed payloads including user-facing errors; transport errors stay in the errors array.
- Set query depth/cost limits, disable production introspection unless required, and plan field-level authorization (
backend-authorization) — the resolver is the enforcement point.
- Document the unit as it is built — the schema/resource files under
docs/<app>/api/ (../../application-documentation).
Required Workflow
- Make and record the GraphQL-vs-REST fit decision.
- Model the schema from the domain graph.
- Plan resolvers + dataloader boundaries for every relation.
- Define pagination, mutation, and error conventions.
- Set cost/depth limits and authorization per field/resolver.
- Record the schema design in the API contract.
Decision Rules
- One client with fixed screens rarely justifies GraphQL.
- Every relation resolver gets a batching strategy or a recorded reason it doesn't need one.
- Authorization is enforced per resolver/field — a query reaching a resolver proves nothing (
ownership-authorization).
- Public APIs get persisted queries or cost limits; never unlimited anonymous query shapes (
rate-limiting).
Rules
- Schema evolves additively; deprecate fields, don't break them (
api-contracts).
- No resolver reads another domain's tables directly (
backend-api-architecture).
- Errors never leak internals (
backend-error-handling).
Anti-Patterns
- Adopting GraphQL for one client "to be modern."
- Schema mirroring database tables 1:1.
- Relation resolvers issuing per-item queries (N+1).
- Authorization only at the query root, leaving nested fields open.
- Unbounded lists and unlimited query depth on public endpoints.
Validation Checklist
Definition of Done
A recorded fit decision and, if GraphQL, a schema + resolver design with N+1 protection, pagination, limits, and resolver-level authorization — registered in the API contract.
Related Skills
rest-api-design, api-contracts, backend-authorization, ownership-authorization, rate-limiting, backend-performance, ../../database/database-performance, ../../application-documentation.
Related Knowledge
../../../knowledge/ (domain graph, client needs).
Related References
../../../references/backend/api/ (schema conventions, when populated).
Context Loading Guidance
- Requires: domain model, client data-shape needs, auth model summary.
- Does not require: database internals, resolver implementations.
- May load:
api-contracts, backend-authorization.
- Stop when: the fit decision (and schema design, if chosen) is recorded.
Token Efficiency Guidance
Decide fit from the client-needs summary before designing anything. Express the schema as type sketches, not full SDL dumps.
1---2name: graphql-api-design3description: Use to decide whether GraphQL fits and to design a GraphQL API — schema/type design, resolvers, N+1 protection (dataloaders), pagination (connections), mutations/errors, query cost limits, and field-level authorization.4---56# GraphQL API Design78## Purpose910Evaluate GraphQL against the project's needs and, if chosen, design the schema, resolver strategy, N+1 protection, pagination, and security limits — as a contract, not code.1112## When to Use1314- When clients need flexible, nested data selection (multiple frontends with divergent data needs).15- **Not** when a straightforward REST surface serves the clients — evaluate first, don't assume.1617## Inputs1819- Domain model, client list and their data-shape needs.20- Auth model (`backend-authentication`, `backend-authorization`).2122## Discovery Questions2324- Do clients genuinely need flexible selection/nesting, or would a few REST endpoints do?25- What are the deepest/heaviest queries clients will run?26- Who may introspect the schema in production?2728## Responsibilities2930- **Fit decision first:** GraphQL earns its complexity with multiple clients needing different shapes of the same graph; otherwise recommend REST (`rest-api-design`).31- Design the schema from the **domain graph**, not the database tables; nullable vs non-null deliberately.32- Plan resolver data loading with **dataloaders/batching** — N+1 is the default failure, design against it explicitly.33- Use **connection-style pagination** for lists; no unbounded list fields.34- Design mutations with typed payloads including user-facing errors; transport errors stay in the errors array.35- Set **query depth/cost limits**, disable production introspection unless required, and plan **field-level authorization** (`backend-authorization`) — the resolver is the enforcement point.36- Document the unit as it is built — the schema/resource files under `docs/<app>/api/` (`../../application-documentation`).3738## Required Workflow39401. Make and record the GraphQL-vs-REST fit decision.412. Model the schema from the domain graph.423. Plan resolvers + dataloader boundaries for every relation.434. Define pagination, mutation, and error conventions.445. Set cost/depth limits and authorization per field/resolver.456. Record the schema design in the API contract.4647## Decision Rules4849- One client with fixed screens rarely justifies GraphQL.50- Every relation resolver gets a batching strategy or a recorded reason it doesn't need one.51- Authorization is enforced **per resolver/field** — a query reaching a resolver proves nothing (`ownership-authorization`).52- Public APIs get persisted queries or cost limits; never unlimited anonymous query shapes (`rate-limiting`).5354## Rules5556- Schema evolves additively; deprecate fields, don't break them (`api-contracts`).57- No resolver reads another domain's tables directly (`backend-api-architecture`).58- Errors never leak internals (`backend-error-handling`).5960## Anti-Patterns6162- Adopting GraphQL for one client "to be modern."63- Schema mirroring database tables 1:1.64- Relation resolvers issuing per-item queries (N+1).65- Authorization only at the query root, leaving nested fields open.66- Unbounded lists and unlimited query depth on public endpoints.6768## Validation Checklist6970- [ ] Fit decision recorded (GraphQL justified over REST).71- [ ] Schema modeled from the domain graph; nullability deliberate.72- [ ] Dataloader/batching plan per relation.73- [ ] Connection pagination on all lists.74- [ ] Depth/cost limits + introspection policy set.75- [ ] Field/resolver-level authorization planned.7677## Definition of Done7879A recorded fit decision and, if GraphQL, a schema + resolver design with N+1 protection, pagination, limits, and resolver-level authorization — registered in the API contract.8081## Related Skills8283`rest-api-design`, `api-contracts`, `backend-authorization`, `ownership-authorization`, `rate-limiting`, `backend-performance`, `../../database/database-performance`, `../../application-documentation`.8485## Related Knowledge8687`../../../knowledge/` (domain graph, client needs).8889## Related References9091`../../../references/backend/api/` (schema conventions, when populated).9293## Context Loading Guidance9495- **Requires:** domain model, client data-shape needs, auth model summary.96- **Does not require:** database internals, resolver implementations.97- **May load:** `api-contracts`, `backend-authorization`.98- **Stop when:** the fit decision (and schema design, if chosen) is recorded.99100## Token Efficiency Guidance101102Decide fit from the client-needs summary before designing anything. Express the schema as type sketches, not full SDL dumps.