REST vs GraphQL
When each makes sense, what they share, and why most teams should reach for REST first.
REST and GraphQL are both ways to expose a backend to a client over HTTP. The framing is often "GraphQL is better than REST" or vice versa, but the truth is more boring: they are different tools that fit different situations. Pick the one that solves your actual problems.
What they share
Both run over HTTP. Both use JSON for payloads. Both let a client read and write data. Both can be authenticated with bearer tokens, rate-limited, cached at the edge, monitored with the same tools. The differences are in theshape of the API, not the transport.
What REST looks like
A REST API exposes a fixed set of URLs, each returning a fixed shape. To assemble a complex view, you make several calls:
GET /users/123
-> { id, name, email }
GET /users/123/posts
-> [{ id, title }, ...]
GET /posts/456/comments
-> [{ id, body, author }, ...]
Three round-trips for "user with their posts and the comments on each post". Pros: each endpoint is simple and cacheable independently. Cons: you over-fetch (every endpoint returns its full shape, even fields you do not need) and under-fetch (you have to make multiple calls for one screen).
What GraphQL looks like
A GraphQL API exposes one URL (/graphql) and a schema. The client sends a query describing exactly the shape they want:
query {
user(id: 123) {
name
posts {
title
comments {
body
author { name }
}
}
}
}
One round-trip for the same data. Pros: client decides what fields come back, no over-fetch, related data nests naturally. Cons: caching is harder (every query is unique), the schema-first approach is heavier, error handling is fiddly (a query can partially succeed).
Where REST wins
- Caching. GETs in REST are URL-keyed; CDNs and browsers cache them transparently. GraphQL queries are POSTs with arbitrary bodies; caching needs explicit work (persisted queries, normalised client caches).
- File uploads and binary data. Multipart uploads work the way they always have on REST. GraphQL has a multipart spec, but it is awkward.
- Public APIs. Discoverability via URLs is human-friendly. With Stripe, Twilio, or GitHub's REST API, users can read documentation and curl an endpoint immediately. GraphQL needs a tool (GraphiQL or similar) to be approachable.
- Operational simplicity. Smaller surface area, easier to monitor (per-endpoint latencies), fewer subtle ways to slow down the database.
- Status codes. REST uses HTTP semantics (200, 401, 404, 422, 429). GraphQL collapses everything into 200 with errors in the body. Tooling that branches on status codes (load balancers, CDNs, alarms) prefers REST.
Where GraphQL wins
- Aggregating across types in one round-trip. A "feed" page that needs the user, their friends, recent posts and comments is a single GraphQL query and three or four REST calls.
- Mobile bandwidth. No over-fetch can save real bytes on slow networks.
- Strongly-typed client. GraphQL's schema becomes typed code on the client. Tools like Relay and Apollo make this seamless. REST needs OpenAPI plus a code generator to match.
- Iterating on the client. When the client wants a new field, they query for it. No backend deploy needed (assuming the field exists in the schema).
- Microservice composition. GraphQL's federation lets one schema span multiple backend services. The client does not see the boundary.
The N+1 problem cuts both ways
REST encourages multiple calls; GraphQL hides them but the database may still get hit N+1 times if your resolvers are naive. Solving N+1 in GraphQL means using DataLoader (or equivalent) to batch within a single query. Solving it in REST means designing the right endpoints (/users?include=posts) or living with the round-trips.
How to choose
Three questions:
- How varied are your client needs? If every client needs roughly the same data, REST. If clients need wildly different subsets, GraphQL.
- Who builds your clients? Internal teams that move with the API: GraphQL is fine. Public APIs consumed by strangers: REST is more approachable.
- What is your operational budget? REST is simpler to monitor, scale, and debug. GraphQL has more moving parts.
Tie-breaker: REST first. If you outgrow it, you can layer GraphQL in front of REST endpoints. The reverse migration is harder.
What about tRPC, gRPC, JSON-RPC?
Three more flavours worth knowing:
- tRPC. End-to-end TypeScript types between server and client. Excellent for full-stack TS apps where you control both sides.
- gRPC. HTTP/2 + Protocol Buffers. Strongly typed, fast, hard to debug. Ideal for service-to-service inside a backend; awkward for browser clients.
- JSON-RPC. Simpler than GraphQL, fixed function-call shape. Used by Ethereum nodes and a few other places. Niche.
For typical product API work, the choice is REST or GraphQL. Pick REST unless you have a concrete reason to pick GraphQL.
More primers
What is a REST API?
A plain-English explanation of REST, HTTP methods, resources, and why almost every modern web service speaks this style.
What is JSON?
JSON syntax in 5 minutes: objects, arrays, strings, numbers, why it replaced XML, and the gotchas that bite beginners.
What is HTTP?
Request/response, headers, methods, status codes - the protocol the web has run on since 1991.