GraphQL vs REST
GraphQL and REST are two ways to design an API, and the choice is real — not a matter of one being universally "better." REST exposes many resource URLs with fixed response shapes; GraphQL exposes one endpoint and lets the client compose the shape it needs. Each makes different things easy and different things hard. This page sets them side by side on fetching, caching, errors, versioning, and tooling, looks at what each does well and badly, and gives an honest rule for choosing — including the increasingly common answer: use both.
The same request, two paradigms
Goal: show a user, their last 3 orders, and each order's item names.
REST — multiple round-trips, fixed shapes (often over-fetching):
GET /users/42 → {id, name, email, address, ...30 fields}
GET /users/42/orders?last=3 → [{id, total, ...}, ...]
GET /orders/o1/items → [...] ┐
GET /orders/o2/items → [...] ├ N more calls (under-fetching)
GET /orders/o3/items → [...] ┘
GraphQL — one request, exact shape:
POST /graphql
{ user(id:"42") { name orders(last:3) { total items { name } } } }
→ exactly those fields, one round-tripSide by side
Concern | REST | GraphQL |
|---|---|---|
Endpoints | Many URLs, one per resource | One ( |
Response shape | Fixed by the server | Chosen by the client |
Over/under-fetching | Common | Eliminated by design |
Round-trips for nested data | Often several | One |
HTTP caching | Excellent — built-in ( | Hard — needs app-level / client caching |
Typed contract | Optional (OpenAPI/Swagger add-on) | Built-in & mandatory (the schema) |
Versioning | Usually | Versionless — add fields, deprecate old ones |
File uploads / binary | Natural | Awkward (needs a spec/multipart workaround) |
Error model | HTTP status codes |
|
Learning curve / setup | Low — it's just HTTP | Higher — schema, resolvers, server |
Where each genuinely wins
GraphQL shines when: REST shines when:
• many clients with different data needs • simple CRUD / resource-shaped data
(web + iOS + Android) hit one API • HTTP caching/CDNs matter a lot
• screens aggregate many related • public API consumed by unknown clients
resources (avoid waterfalls) • file uploads / streaming / binary
• rapidly evolving frontend product • you want minimal moving parts
• a strongly-typed client contract • the team already knows REST cold
drives codegen & autocompletion