
GraphQL
GraphQL gives clients a flexible query language over a typed schema. That can remove over-fetching and speed up product iteration, especially when many clients need slightly different shapes of the same data. The tradeoff is that query cost moves from the route list into your resolver graph, where careless field access can create hidden fan-out.
Minimal Example
type Query {
product(id: ID!): Product
}
type Product {
id: ID!
name: String!
price: Money!
reviews(limit: Int = 5): [Review!]!
}
query ProductCard($id: ID!) {
product(id: $id) { name price reviews(limit: 3) { rating } }
} What It Solves
- Lets clients ask for just the fields they need without adding a new REST shape per screen.
- Makes the contract explicit through a schema that tooling can validate, diff, and document.
- Supports composition across domains when the graph mirrors real product relationships.
Failure Modes
- Shipping resolver trees with no batching and rediscovering the N+1 problem at runtime.
- Treating the schema as a database mirror instead of a product contract.
- Allowing unbounded nested queries without complexity limits or timeouts.
Production Checklist
- Batch field access with loaders and instrument per-field latency.
- Set depth and cost limits for public or high-cardinality queries.
- Version by deprecation and schema evolution, not by random field removal.
Closing
GraphQL works well when the schema stays product-focused and the execution engine stays heavily instrumented. Flexibility without cost control becomes chaos quickly.









