What you'll learn
Quick Answer
REST exposes many endpoints, each returning a fixed shape, so clients often fetch more data than they need or make several calls to assemble a screen. GraphQL exposes one endpoint where the client specifies exactly which fields it wants, which removes over-fetching and round trips. The trade is complexity: GraphQL gives up simple HTTP caching, needs extra work to avoid database N+1 problems, and returns HTTP 200 even for errors. REST remains the right default unless you have many clients with genuinely different data needs.
The Problem GraphQL Was Built to Solve
Consider a profile screen showing a user's name, their last three posts, and the comment count on each. With REST that is typically several calls.
GET /users/42 → full user object (30 fields, you need 1)
GET /users/42/posts?limit=3 → three posts
GET /posts/101/comments → to count them
GET /posts/102/comments
GET /posts/103/commentsTwo problems are visible. Over-fetching: the user endpoint returns thirty fields when the screen shows one. Under-fetching, or the N+1 round trip: you need another call per post to get its comment count.
On a fast connection this is invisible. On a phone on a patchy mobile network, five sequential round trips is a noticeably slow screen. GraphQL was created at Facebook for precisely that situation.
POST /graphql
{
user(id: 42) {
name
posts(limit: 3) {
title
commentCount
}
}
}One request, one response, exactly the fields asked for and nothing else. When you have many different clients — web, iOS, Android, a watch — each needing different subsets of the same data, this is genuinely transformative.
What REST Still Does Better
Caching. This is the biggest practical loss and it is often glossed over. REST rides on HTTP: a GET to /users/42 can be cached by the browser, by a CDN, by a reverse proxy, using ETags and Cache-Control that already exist. GraphQL sends everything as a POST to one URL, so none of that machinery applies. You end up implementing caching in the client library and at the resolver level — work that REST gets free.
Simplicity. REST is just HTTP. Any developer, any language, curl, a browser address bar. GraphQL needs a schema, resolvers, usually a client library, and a build step for typed clients. That is real setup and real ongoing maintenance.
Error handling and status codes. REST uses the status code, so monitoring, retries and alerting all work without configuration. GraphQL returns 200 OK even when something failed, with an errors array in the body. Every layer that watches status codes therefore sees healthy traffic while your API is failing, until you wire up something custom.
File uploads and streaming are straightforward in REST and awkward in GraphQL, needing extra specifications.
Rate limiting. REST counts requests. In GraphQL one request can be trivial or can request half the database, so limiting requires computing query cost and enforcing depth limits.
The N+1 Trap Moves, It Does Not Disappear
This surprises teams who adopt GraphQL expecting fewer queries. It removes N+1 network calls from the client. It can easily create N+1 database queries on the server.
Resolvers run per field, per object. Ask for 50 posts and each post's author, and the naive implementation runs one query for the posts and then fifty separate author queries.
Client sees: 1 clean request
Database sees: 1 + 50 queriesThe fix is a batching layer such as DataLoader, which collects the individual author lookups within a tick and issues one WHERE id IN (...). It works well, but it is mandatory infrastructure rather than an optimisation — a GraphQL API without batching will fall over under real traffic.
So the honest framing is that GraphQL moves complexity from the client to the server. The client gets a much nicer interface; the server takes on query planning, batching, depth limiting and cost analysis that REST never asked of it.
When to Use Which
Use REST when you have one main client and control both ends; when your data is naturally resource-shaped, which most CRUD applications are; when HTTP caching matters, especially for public read-heavy content; when the team is small and every added moving part costs; or when you are building a public API that must be trivially usable by strangers.
Use GraphQL when several clients need genuinely different shapes of the same data; when mobile round trips are a measured problem rather than a suspected one; when the frontend iterates fast and constantly needs slightly different field combinations; or when you are aggregating several backend services behind one interface.
A note on the middle ground. These are not exclusive. Plenty of systems serve REST for public, cacheable, simple endpoints and GraphQL for the complex internal dashboard. Adding GraphQL to an existing REST API as an extra layer is a common and reasonable path.
If you are building your first API, or a project for your portfolio, REST is the right choice. You will understand HTTP better, deploy it anywhere, and avoid maintaining a schema layer for a problem you do not have yet. GraphQL on a single-client CRUD app is complexity bought with nothing in return.
What Interviewers Actually Ask
The question is rarely "which is better". It is usually "when would you pick one over the other", and the answer they want shows you understand trade-offs rather than trends.
A strong answer names the problem GraphQL solves — over-fetching and multiple round trips across diverse clients — and then names what it costs: HTTP caching, error handling through status codes, rate limiting, and the batching work needed to avoid database N+1.
Then state a default. Something like: REST unless there are several clients with materially different data needs, because REST's simplicity and free caching are worth a great deal and GraphQL's benefits only appear at a certain scale of client diversity.
If you have used one in a project, describe a concrete decision you made — a screen that needed four REST calls, or a caching problem GraphQL introduced. A specific example beats a memorised comparison table every time.
