Technology - Non SAP

GraphQL vs REST — The Honest Decision Framework

Most teams pick one and apply it everywhere. REST everywhere because that is what they know. GraphQL everywhere because someone read a blog post in 2021 and got excited. Both approaches cause pain — just different pain.

GraphQL was built to solve real problems that REST genuinely has. REST has real advantages that GraphQL genuinely cannot match. The mistake is not choosing the wrong one. The mistake is treating the choice as universal when it is not.

This post gives you a clear framework for choosing between them. No hedging. No ‘it depends’. Just the actual decision criteria — and what each approach costs you when you use it where it does not belong.

🔗 Foundation posts

REST API Design Principles covers the fundamentals of REST — how resources, HTTP verbs and status codes work. Read that first if REST is still fuzzy.
OData Protocol in SAP is directly relevant if you work in the SAP world — OData is REST-based and the concepts here apply directly.

The core difference — one idea each

REST was introduced by Roy Fielding in his 2000 doctoral dissertation. The central idea: model everything as a resource and use standard HTTP verbs to interact with it. A user is a resource. An order is a resource. You get users with GET /users/1. You create orders with POST /orders. Each resource has its own URL, and HTTP handles the rest.

GraphQL was built at Facebook in 2012 and open-sourced in 2015. The problem they were solving was mobile performance — specifically, fetching exactly the data a mobile app needed without the overhead of multiple REST calls. The central idea: expose one endpoint and let the client specify exactly what data it wants in a query.

That is the whole thing. REST: server decides what each endpoint returns. GraphQL: client decides what it gets. Everything else — the tooling differences, the caching trade-offs, the N+1 problem — flows from that one distinction.

Two-panel diagram on white background comparing REST returning all fields with over-fetching highlighted in red on the left versus GraphQL returning exactly the requested fields in green on the right

The two problems GraphQL was built to solve

REST has two well-known failure modes when clients have varied or complex data needs. GraphQL was designed specifically to fix them.

Over-fetching

Your mobile app needs a user’s name and profile photo. The REST endpoint GET /users/1 returns a full user object — name, email, address, phone number, account settings, preferences. The app uses two fields and discards the rest.

On desktop with a fast connection, this is a minor inefficiency. On a 3G mobile connection in 2012 at Facebook scale — hundreds of millions of users — it was a real problem. Bandwidth costs money. Parsing unused data costs battery.

Under-fetching and the N+1 REST problem

The opposite problem. You need a user’s name plus their last five posts. One REST call gets you the user. Another call gets you the posts. Then you need the author of each post comment — five more calls. One screen, seven HTTP requests.

GraphQL solves this with a single query: ask for the user, their posts, and each post’s comments in one request. The server resolves it all and returns exactly what was asked for.

⚠️ GraphQL has its own version of the N+1 problem — on the server

Ironic but true. If you ask GraphQL for 20 users and each user’s posts, a naive GraphQL resolver makes 1 query for users, then 20 separate queries for posts — one per user. This is the N+1 problem, now server-side.

The solution is the DataLoader pattern — originally built by Facebook. DataLoader batches those 20 post queries into one, reducing them to 2 database calls total. Every serious GraphQL server implementation includes it, but you have to use it deliberately. If you are building GraphQL without DataLoader, you are building a performance problem into your API layer.

Where REST wins — and GraphQL makes things harder

GraphQL is not a universal upgrade. There are scenarios where REST is the right choice and GraphQL adds complexity without benefit.

ScenarioWhy REST wins
Public APIsREST’s URL-per-resource model works perfectly with HTTP caching — CDNs, browser caches, reverse proxies. GET /products/123 is cacheable by any HTTP layer. A GraphQL POST to /graphql with a query body is not, without additional tooling.
Service-to-service in microservicesInternal services have narrow, well-defined contracts. A REST endpoint is simpler, cacheable and easier to test than a GraphQL layer for this pattern.
File uploadsREST handles multipart/form-data naturally over HTTP. GraphQL file upload is possible but non-standard — it requires middleware and workarounds.
Simple CRUD operationsIf your API is straightforward create, read, update, delete — REST is faster to build, easier to understand and has more mature tooling.
Teams new to API developmentGraphQL has a steeper learning curve — schemas, resolvers, query language, DataLoader. REST lets a junior team ship and iterate.

📌 Key Takeaway

REST’s caching advantage is often underestimated. The entire HTTP caching infrastructure — CDNs, Varnish, browser caches — is built around cacheable URLs. GraphQL throws that away by default. For public APIs with high read traffic, this is a meaningful cost.

Where GraphQL wins — and REST gets painful

Three scenarios exist where GraphQL pays back its setup cost clearly.

Multiple client types with different data needs

Your API serves a web app, an iOS app, an Android app, and a third-party integration. Each client needs different fields from the same underlying data. With REST, you have two options: return everything and let clients filter (over-fetch), or build client-specific endpoints (endpoint sprawl). Neither is good.

GraphQL lets each client request exactly what it needs from a single API. The web app gets the full user profile. The mobile app gets name and avatar only. The third-party integration gets account IDs. One API, three different query shapes.

The Backend for Frontend (BFF) pattern

A BFF is an API layer that sits between your services and your clients, shaped to what each client needs. GraphQL is the natural choice here — it aggregates data from multiple upstream services into one query, letting the frontend fetch a full page’s data in a single round trip instead of orchestrating five REST calls.

This is exactly what Facebook built GraphQL to do. It remains one of GraphQL’s strongest use cases.

Rapid frontend iteration

REST APIs often require a backend change every time a frontend needs a new data shape. GraphQL inverts this — the schema defines what is available, and the frontend queries whatever it needs from that schema without touching the backend. Frontend teams move faster. Backend teams are not blocked by UI changes.

BFF architecture diagram on white background showing web app, mobile app and third-party integration sending different queries to a central GraphQL API layer which aggregates from user, orders and product services

Best Practice

GraphQL’s schema is a contract. Define it carefully and version it thoughtfully — adding fields is non-breaking, removing them is. The schema is also self-documenting via introspection, which tools like GraphiQL and Apollo Studio use to generate API explorers automatically. This is a real operational advantage over REST, where documentation is always a separate effort.

Using both — the pattern that actually works in production

The most mature systems do not choose. They use REST and GraphQL for what each does well.

The pattern that appears consistently in production at scale: REST for service-to-service communication and public APIs where caching matters. GraphQL as the client-facing layer — the BFF — that aggregates those services and serves different client types efficiently.

GitHub’s API is a real-world example. GitHub maintains both a REST API (v3, widely used, heavily cached) and a GraphQL API (v4, for clients that need flexible data shapes). They are not competing — they serve different consumers.

📝 Note — MCP as the third option for AI tooling

Model Context Protocol (MCP), launched by Anthropic in November 2024 and donated to the Linux Foundation in December 2025, is emerging as a third API style for one specific context: AI agents that need to discover and call tools dynamically.

MCP is not a replacement for REST or GraphQL for application APIs — it is purpose-built for the AI agent use case. If you are building integrations for LLM-based systems, read the MCP post. If you are building a regular application API, REST and GraphQL are still your options.

The decision framework — when to reach for which

Use this table. No hedging.

ScenarioChooseReason
Public API for external developersRESTHTTP caching, simplicity, broad tooling, familiar to all consumers
Service-to-service in microservicesRESTNarrow contract, cacheable, easy to test and monitor
File uploads or binary dataRESTMultipart/form-data over HTTP — GraphQL workarounds add friction
Simple CRUD with uniform data modelRESTLower complexity, faster to build, easier to debug
Multiple client types with different data needsGraphQLEach client queries exactly what it needs from one API
BFF layer aggregating services for a frontendGraphQLSingle round trip, aggregated data, shaped per client
Rapid frontend iteration without backend changesGraphQLFrontend queries from schema without backend involvement
Real-time data with subscriptionsGraphQLGraphQL subscriptions over WebSocket are native and well-supported
High read traffic on cacheable resourcesRESTCDN and HTTP cache layer works out of the box — GraphQL needs extra infrastructure
Team new to API developmentRESTFaster to learn, more tooling, simpler mental model to start

GraphQL vs REST decision flow diagram on white background showing a three-step decision tree leading to REST for service-to-service and public APIs and GraphQL for multi-client BFF patterns

At a glance — GraphQL vs REST

ConceptOne-line summary
RESTArchitectural style introduced in 2000 — resources identified by URLs, interacted with via HTTP verbs
GraphQLQuery language introduced by Facebook in 2012 — one endpoint, client specifies exactly what data it needs
Over-fetchingREST returns more data than the client needs — GraphQL eliminates this by letting clients define the response shape
Under-fetchingREST requires multiple requests to assemble a full page — GraphQL resolves this with a single query
N+1 problem (GraphQL)Nested resolvers can trigger N database queries for N items — solved with the DataLoader batching pattern
HTTP cachingREST aligns naturally with CDN and browser caching — GraphQL does not by default
BFF patternBackend for Frontend — GraphQL as the aggregation layer between services and clients
Schema (GraphQL)Strongly typed contract defining available data — self-documenting, introspectable
When to use RESTPublic APIs, service-to-service, file uploads, simple CRUD, high-cacheability requirements
When to use GraphQLMultiple client types, BFF layer, rapid frontend iteration, real-time subscriptions
Using bothThe production pattern — REST for services and public APIs, GraphQL for the client-facing layer

What to take away

The REST vs GraphQL debate has been running for a decade and it is still generating heat because people frame it as a permanent choice. It is not. It is a per-use-case choice — and most systems with enough complexity end up using both.

The real cost of getting this wrong is not a failed project. It is a year of working around the wrong tool. REST applied to a multi-client product with complex data needs produces endpoint sprawl and over-fetching. GraphQL applied to a simple CRUD API or a service mesh produces unnecessary complexity, a caching headache, and a DataLoader you now have to maintain.

Match the tool to the problem. REST for the parts of your system that are stable, cacheable and resource-oriented. GraphQL for the parts that serve multiple clients with different needs. Once you see the two patterns side by side in a real system, the choice becomes obvious — and you stop asking which one wins.

🔗 Related posts on this site

REST API Design Principles — the fundamentals of REST: resources, verbs, status codes and what makes a REST API well-designed.
OData Protocol in SAP — OData is REST with a specification on top. If you work with SAP APIs, this is where the GraphQL vs REST decision becomes concrete.
API Security Essentials — authentication, authorisation and the OWASP API Top 10 apply equally to REST and GraphQL — with some GraphQL-specific considerations worth knowing.
MCP — Model Context Protocol Explained — the third API style emerging for AI agent tooling in 2025-2026, and when it applies instead of REST or GraphQL.

Published on rakeshnarayan.com — Articles

URL: https://rakeshnarayan.com/articles/graphql-vs-rest-the-honest-decision-framework/