Comparison
GraphQL or REST? Count your clients, not endpoints
The verdict
Default to REST. It powers around 83 percent of public APIs, 93 percent of teams still rely on it, and it gets HTTP caching, CDN behavior, curl debugging and status-code semantics for free. Add GraphQL when you have three or more meaningfully different clients pulling different shapes from the same data, or a graph deep enough that REST turns into a request waterfall. GraphQL sits near 28 percent adoption and grew roughly 340 percent since 2023, but 67 percent of large organizations run both, and that hybrid is the actual answer more often than either pure position.
There is a third option this page will not pretend does not exist. If you own both the client and the server in one TypeScript repository and no external party consumes the API, tRPC gives you end-to-end type safety with no schema file, no code generation, and none of the operational surface either of the other two carries. It is the right answer for a surprising number of full-stack applications, and it is the wrong answer the moment a third party needs a contract.
REST vs GraphQL on performance, caching and team cost
Latency and throughput figures below are published third-party measurements and depend entirely on query shape. The directional result is consistent: GraphQL wins on complex nested reads, REST wins on volume of simple ones.
| Dimension | REST | GraphQL |
|---|---|---|
| Complex reads | Multiple round trips. One published test measured about 250 ms where the data spanned several resources. | One request for the whole shape. The same test measured about 180 ms, a 28 percent improvement. |
| Simple reads | Roughly 20,000 requests per second in the same suite, using about 20 percent less CPU. | Roughly 15,000 per second. Parsing, validating and resolving a query is not free. |
| Caching | Free and automatic. URLs are cache keys, so a CDN, a browser and a proxy all help with no work from you. | You build it. Persisted queries plus a CDN that understands them, or client-side normalized caching, or both. |
| Over-fetching | Endpoints return fixed shapes, so a mobile client downloads fields it will never render. | Clients request exactly the fields they need, which is the original and still the strongest argument for it. |
| Contract | OpenAPI if you maintain it. Drift between spec and implementation is a chronic, well-known problem. | The schema is executable and always accurate. Client codegen and introspection follow from it automatically. |
| Operations | Rate limit by requests, authorize per route, read status codes in logs. Every tool you own already understands it. | Rate limit by query complexity, authorize per field, and instrument resolvers. All solvable, none automatic. |
| Team cost | Any backend developer is productive immediately. There is nothing to learn that they do not already know. | Real ramp-up: DataLoader for N+1, complexity limits, error conventions, and a gateway if you federate. |
When each API style is the right call
Choose REST when
- The API is public and third parties integrate with it. Every developer on earth can already consume REST.
- Responses are cacheable and a CDN doing that work for free is worth more than trimming response fields.
- The surface is mostly CRUD over a handful of resources, which describes the majority of business software.
- You handle uploads, downloads, streaming, or webhooks, where HTTP semantics are the feature rather than the wrapper.
- You run on serverless where per-request CPU is billed, and 20 percent less CPU per request is a real line item.
Choose GraphQL when
- Web, iOS, Android and a partner integration all read the same data in different shapes and change on different schedules.
- Screens are deeply nested - a user, their orders, each order's items, each item's supplier - and REST becomes a waterfall.
- You are consolidating several backend services behind one schema, where federation lets teams own subgraphs independently.
- Mobile bandwidth or battery is a product concern and shipping only requested fields measurably helps.
- You want a typed contract that cannot drift, with generated clients falling out of it for free.
The hybrid pattern most large teams landed on
The dominant architecture in 2026 is not a choice between these two, it is a layering. Service-to-service traffic stays REST or gRPC because it is simple, fast and observable with tools everyone already runs. A single GraphQL graph sits at the edge for client applications, giving product teams one endpoint and a typed schema. Netflix, GitHub, Shopify, Airbnb and The New York Times all run some version of this, and the reason is that the two technologies solve different problems that happen to share a transport.
Federation is how organizations scale that graph past one team. More than half of enterprises report GraphQL in production, and the supergraph model - independent subgraphs composed into one schema behind a router - is the standard way to keep several teams from fighting over a single monolithic schema file. It is also where GraphQL stops being a library choice and becomes platform work: composition checks in CI, contract-based visibility so partners see a subset of the graph, and runtime governance for query cost. Do not adopt federation because the diagram is appealing; adopt it when you have the team count that makes it necessary.
The costs that sink GraphQL projects are always the same four, and none of them are visible in a tutorial. First, caching: you traded free HTTP caching for infrastructure you now maintain. Second, N+1 queries, which DataLoader solves only if every resolver author remembers to use it. Third, authorization, which moves from route middleware to per-field checks and gets subtle fast. Fourth, rate limiting, which has to become query-complexity scoring because one request can be arbitrarily expensive. Each is an engineering-week or more, and a team of three shipping a CRUD product should not spend twelve.
An honest note on the other direction: teams that chose REST and then bolted on twenty ?include= parameters and six bespoke aggregate endpoints have built a worse GraphQL. If your REST API has grown a query language, that is the signal to adopt the real one. The specification and federation resources are at graphql.org.
Where this fits in a full stack
The REST and backend API stack guide takes this decision and builds the rest around it: framework, validation, authentication, documentation and deployment. The backend and runtime layer covers the servers and frameworks that implement either style.
If you went with REST, getting status codes right is most of a good API. The HTTP status codes cheatsheet is the fast reference for that. Other close calls live in the comparisons index.