REST vs GraphQL
REST vs GraphQL for API design: fewer round trips vs simpler caching, and which fits your client's actual data needs.
Last updated
The short answer
REST is simpler to build, cache and reason about, and it's the safer default for a small API with a handful of clients. GraphQL earns its extra complexity when multiple clients need different shapes of the same data and round trips are expensive — mobile apps on flaky networks, or one backend serving many different frontends.
| Dimension | REST | GraphQL |
|---|---|---|
| Endpoints | Many, one per resource | One, queries shape the response |
| Over-fetching | Common — fixed response shape | Avoided — client asks for fields |
| Caching | Free via HTTP/CDN caching | Needs custom client-side caching |
| Versioning | New endpoints or /v2 prefix | Evolve schema, deprecate fields |
| Learning curve | Low — plain HTTP verbs | Higher — schema, resolvers |
Choose REST when
- →You have one client or a few similar ones, and each screen needs roughly the response the endpoint already returns.
- →You want HTTP caching (CDNs, browser cache, ETags) to just work without extra infrastructure.
- →Your team is small and the extra machinery of a schema and resolver layer isn't worth it yet.
Choose GraphQL when
- →Different clients — web, iOS, a partner integration — need meaningfully different slices of the same underlying data.
- →Round trips are expensive and stitching together several REST calls per screen is the actual problem you're solving.
- →The API is large enough that a typed schema and introspection genuinely help client developers move faster.
The catch nobody mentions
GraphQL moves the N+1 query problem from 'obviously your fault' to 'hidden inside a resolver' — a naive resolver that fetches each field's data separately can issue hundreds of database queries for one GraphQL request, and it looks fine until real traffic hits it. Batching (DataLoader or equivalent) isn't optional, it's the price of admission.
Questions
Does GraphQL eliminate over-fetching?
For the client, largely yes — you request the fields you want. On the server the resolvers may still fetch everything and discard the rest, so the saving is on the wire rather than in the database unless you build for it.
What is the N+1 problem here?
A query for a list plus a nested field can run one database query per item. It is the defining GraphQL performance trap, and the standard answer is a batching layer such as DataLoader — which is extra machinery REST does not need.
Why is caching harder?
Because everything is a POST to one endpoint, so HTTP caching, CDNs and browser caches have nothing to key on. REST gets that for free from URLs and cache headers, and GraphQL clients rebuild it in application code.
Is a GraphQL endpoint a denial-of-service risk?
It can be. A deeply nested query is cheap to write and expensive to resolve, so a public endpoint needs depth limits, complexity scoring or persisted queries. REST endpoints have a fixed cost by construction.
Which is better for a public API?
REST, usually. It is easier to cache, easier to rate-limit meaningfully, and easier for consumers to use with tools they already have. GraphQL earns its keep with many varied clients you control, particularly mobile.
Can I offer both?
Yes, and many teams do — GraphQL for their own front-ends, REST for third parties. Both then need maintaining and documenting, which is a real cost rather than a free hedge.