Overview
GraphQL is a query language for APIs that lets a client fetch exactly the data it needs, in the shape it needs. This article organizes GraphQL at the level you need to make an adoption decision: when to choose it and what trade-offs it brings. It focuses on design decisions rather than implementation details.
For an introduction with examples, see the separate post What is GraphQL? A Complete Guide with Examples. This article sticks to adoption and operations.
Key characteristics of GraphQL
Three points matter when you weigh adoption.
A typed schema
GraphQL defines types in a schema. The schema becomes the contract between server and client, and it makes the available fields and return types explicit.
A single endpoint and a query language
Where REST exposes many endpoints, GraphQL sends queries to a single endpoint. The client names the fields it wants in the query.
It removes over-fetching and under-fetching
With REST, each endpoint returns a fixed shape. That leads to over-fetching, where you pull data you do not need, and under-fetching, where you call several times. GraphQL fetches only the fields you ask for, in one query.
GraphQL offers three operations.
- Query (read data)
- Mutation (change data)
- Subscription (a continuous stream of updates from the server)
Where it fits and where it does not
Where it fits
- Diverse clients. When web and mobile need different data, each client shapes its own query
- A BFF (Backend for Frontend) that aggregates several data sources into one API tuned for the frontend
- Screens whose data needs vary widely, where you want to avoid over-fetching
Where it does not fit
- APIs that only do simple CRUD. REST often suffices, and the extra complexity does not justify itself
- File transfer or plain resource retrieval. REST maps to HTTP more naturally
- Cases that depend heavily on HTTP caching. GraphQL usually POSTs to one endpoint, so URL-based caching barely helps
Trade-offs
This table pairs each benefit with its cost.
| Aspect | Benefit | Cost |
|---|---|---|
| Fetching | The client gets exactly what it needs in one round trip | Server load varies with the query, which makes it hard to predict |
| Contract | The schema acts as a typed contract | You must design and evolve the schema |
| Surface | One endpoint consolidates access | HTTP caching barely helps |
| Performance | Fewer round trips | The N+1 problem appears easily |
Operational concerns
These points start to matter once you run GraphQL in production.
- The N+1 problem: resolving nested fields tends to multiply queries to the data source. Batch them with a tool such as DataLoader to cut the count
- Query cost control: deep nesting and large queries strain the server. Set depth limits, cost analysis, and timeouts
- Persisted queries: allowing arbitrary queries raises load and security concerns. Consider allowing only pre-registered queries
- Authorization: you often need field-level access control. Align the schema design with the authorization design
- Schema management: when several teams share a schema, set rules for composition and for breaking changes
Choosing between REST, gRPC, and GraphQL
- REST fits public APIs, simple CRUD, and cases that value HTTP caching
- GraphQL fits diverse clients, data aggregation, and screens with varied fetch requirements
- gRPC fits internal service-to-service calls, low latency, streaming, and shared contracts across languages
The three are not exclusive. A common layout puts GraphQL or REST at the edge and gRPC internally.
Summary
A GraphQL adoption decision comes down to a few questions.
- Do clients need very different data from each other? If so, GraphQL is a strong fit
- Do you want to combine several data sources into one API?
- Can you absorb operations such as N+1, caching, and query-cost control?
When you need to serve data flexibly to diverse clients, GraphQL makes a powerful option. When the API stays simple or caching matters most, REST reads more naturally. Choose based on your requirements and your operational capacity.