REST vs GraphQL — When to Pick Which API Style
Every web application that does anything interesting needs to fetch data — a list of posts, a user profile, a search result, a stock price. The shape of that...
Two Ways to Ask a Server for Data
Every web application that does anything interesting needs to fetch data — a list of posts, a user profile, a search result, a stock price. The shape of that fetching is what people mean by "API style." Two styles dominate the modern web: REST and GraphQL.
REST is older, simpler, and almost everywhere. GraphQL is newer, more flexible, and clusters in specific kinds of applications. Choosing between them is one of the most common architectural decisions on a new project, and it is also one of the most religious — engineers will defend their preference like it is a sports team.
This article is the calm version of the comparison. What each style actually is, what kind of code each one produces, when each one wins, and why the answer for most apps is "REST until proven otherwise."
REST in One Page
REST stands for Representational State Transfer, a term coined by Roy Fielding in his 2000 PhD dissertation. The actual REST architectural style is more nuanced than what most people call REST today, but the working version everyone uses goes like this:
- Resources are nouns. A user, a post, an order, a comment. Each resource has a URL.
- Methods are verbs.
GETto read,POSTto create,PUTto replace,PATCHto update part,DELETEto remove. - Status codes carry the result.
200for success,404for not found,401for unauthenticated, etc.
A typical REST API for blog posts:
GET /api/posts → list all posts
GET /api/posts/42 → get post 42
POST /api/posts → create a new post (body has the data)
PUT /api/posts/42 → replace post 42
PATCH /api/posts/42 → update part of post 42
DELETE /api/posts/42 → delete post 42
GET /api/posts/42/comments → list comments on post 42
POST /api/posts/42/comments → add a comment to post 42
That is it. URLs are nouns, methods are verbs, the response is JSON shaped however the server decides. Every web framework — Express, Flask, Rails, Spring, Laravel — gives you this pattern in five minutes.
The benefits are well-known: caching is free (HTTP caches GET responses by URL), the structure is intuitive, every tool on the planet supports it, and any browser can hit it. The drawbacks are also well-known and form the case for GraphQL.
GraphQL in One Page
GraphQL is a query language for APIs, designed at Facebook in 2012 and open-sourced in 2015. Instead of many endpoints with fixed response shapes, GraphQL gives you one endpoint (usually /graphql) where the client sends a query describing exactly what fields it wants.
A typical GraphQL request:
query {
post(id: 42) {
title
body
author {
name
avatar
}
comments(limit: 5) {
body
author { name }
}
}
}
The response is JSON in the exact shape the client asked for — no extra fields, no missing fields. Mutations (writes) look similar:
mutation {
addComment(postId: 42, body: "Great post!") {
id
createdAt
}
}
GraphQL servers expose a schema that defines every type, field, and relationship. Tooling reads the schema to give you autocomplete, type checking, and a documentation page generated automatically. The schema is the contract; the queries are constrained to what the schema allows.
The benefits cluster around three properties: predictable response shape (the client decides what fields), single round-trip for related data (post + author + comments in one request instead of three), and strong typing (the schema is machine-readable and IDE-enforceable).
Where REST's Pain Points Show Up
REST is wonderful for simple CRUD APIs. It starts to hurt in three specific situations:
Over-fetching. A mobile app shows a list of posts. The REST endpoint returns every field of every post — title, body, author, tags, view count, related links — when the list view only displays the title and author name. The mobile app downloads ten times the data it actually uses. On a 4G connection, this is real seconds.
Under-fetching. A page needs the post, the author, and the comments. In REST, that is three separate requests (/posts/42, /users/7, /posts/42/comments), each with its own latency. The page is slow because the requests have to chain. People work around this by adding query parameters (?include=author,comments) or building bespoke aggregator endpoints, which always feel like hacks.
API versioning. Once the API is published, changing a response shape breaks every client. Teams maintain v1, v2, v3 of the API in parallel, deprecate the old ones, and migrate clients carefully. The complexity grows with the number of clients and platforms.
For a single-team app with one frontend, none of this is a big deal. For a multi-platform product (iOS, Android, web, Apple Watch, partner integrations), all three of these become daily problems. That is where GraphQL gets adopted.
Where GraphQL's Pain Points Show Up
GraphQL is not a free upgrade. It introduces its own complications, and for small teams the cost can outweigh the benefit.
Caching is hard. REST gets HTTP caching for free — every GET is a URL, every URL is a cache key. GraphQL has one URL (POST /graphql), so HTTP caches are useless. You end up needing a client-side cache (Apollo Client, urql, Relay) and often a server-side cache (DataLoader for batching, Redis for shared state). The infrastructure cost is real.
N+1 queries. Naive GraphQL resolvers turn one query for "100 posts and their authors" into 1 + 100 = 101 database queries. Solving this requires DataLoader, query batching, and careful resolver design. New GraphQL teams hit this within their first month.
Authorization gets complex. In REST, you check permissions per endpoint — easy to reason about. In GraphQL, a single query can touch ten resolvers across ten types, and each one might need different permission rules. Teams build custom directives or middleware to handle this consistently. It works, but it is more code.
Tooling has a learning curve. A backend engineer needs to learn the schema language, resolvers, federation if you scale, and a specific server library (Apollo Server, GraphQL Yoga, Hasura, etc.). A frontend engineer needs Apollo Client or similar. The cognitive overhead is real for a team that does not need it.
Specs and best practices are still evolving. GraphQL has been stable for years, but federation, subscriptions, file upload, and streaming all have multiple competing approaches. Picking one and changing your mind later is painful.
When to Pick Which
Pick REST when:
- The API is consumed by one frontend you also build.
- The data model is mostly CRUD on independent resources.
- HTTP caching matters (high-traffic public APIs, CDNs).
- The team is small and the engineers are not specifically GraphQL-experienced.
- You need maximum tool compatibility — every monitoring tool, gateway, and SDK supports REST.
Pick GraphQL when:
- Multiple very different clients (mobile, web, partner) consume the same API and each needs different fields.
- The data model has deep relationships and clients constantly need related entities together.
- The frontend team and backend team move at different speeds, and the frontend wants to add fields without backend deploys.
- You are at scale and the over-fetching cost is measurable in user metrics.
- The team has GraphQL experience, or you are willing to invest in learning it.
For most projects, "REST until proven otherwise" is the right default. The over-fetching problem is rarely a real problem at small scale. The under-fetching problem is rarely worse than a couple of round trips. The versioning problem only matters when you have many clients you do not control.
A Hybrid That Works
Real production teams often end up running both. The public API is REST, because partners expect REST. The internal API between the frontend and backend is GraphQL, because the frontend gets the flexibility benefits. The internal services talk to each other over RPC (gRPC, tRPC, or just REST). Each surface uses the right tool.
This is not a contradiction; it is engineering maturity. The styles are not religions. They are tools with different cost-benefit curves, and the boundary of your system is allowed to use multiple.
What About tRPC?
A more recent option worth knowing: tRPC. It is not REST, not GraphQL — it is end-to-end TypeScript types between your backend and frontend. The backend defines functions; the frontend calls them like local functions; the types are shared automatically.
tRPC works only when both sides are TypeScript and run in the same monorepo, but in that specific case it is dramatically simpler than either REST or GraphQL. No API contract to maintain, no schema to write, no client library to configure. For TypeScript-only teams, it is increasingly the default for internal APIs.
If your stack is TypeScript end-to-end, give tRPC a serious look before reaching for either REST or GraphQL.
The 2026 State of Play
A rough survey of where each style sits today:
- REST still powers the vast majority of public APIs (Stripe, GitHub, Twilio, every government data portal). Anything that needs to be consumed by partners you do not control is REST.
- GraphQL is dominant where complex client requirements meet large engineering teams (Facebook, Shopify, GitHub's secondary API, most consumer products with multiple platforms).
- tRPC is the rising default for full-stack TypeScript apps where backend and frontend ship from the same repo.
- gRPC and protobuf dominate internal service-to-service traffic at scale (Google, internal microservices, anywhere binary efficiency matters more than browser compatibility).
Knowing which style fits which slot is the engineering judgment. Picking based on what is fashionable is how teams end up rebuilding their API a year later.
Where This Fits
Lesson 09 of the ABCsteps curriculum has you call real APIs — almost all of them REST. This article is the broader picture so you know not just how to call REST APIs but where REST sits in the landscape and when you would build something different. Lesson 13 then has you write your own API — at that point, this article's decision tree tells you which style to pick for the project's specific needs.
Apply this hands-on · Module B
How Apps Talk: APIs Revealed
Lesson 09 builds against REST APIs. This article shows where GraphQL fits and when REST is still the right call — a decision the lesson assumes you understand.
Open lesson