👋Hi, I'm Waqas — a Software Architect and Technical Consultant specializing in .NET, Azure, microservices, and API-first system design..
I help companies build reliable, maintainable, and high-performance backend platforms that scale.
REST vs GraphQL: over-fetching, versioning, and when GraphQL pays off.
August 21, 2025 · Waqas Ahmad
Read the article
Introduction
This guidance is relevant when the topic of this article applies to your system or design choices; it breaks down when constraints or context differ. I’ve applied it in real projects and refined the takeaways over time (as of 2026).
REST is the default for APIs—simple, cacheable, and widely understood—but fixed response shapes can lead to over-fetching or many endpoints when clients have different data needs. This article compares REST and GraphQL in depth: what each is, strengths and weaknesses, when to choose which, and how to implement both in .NET. For architects and tech leads, starting with REST and adding GraphQL only when multiple clients and varying data needs justify it keeps complexity under control.
For a deeper overview of this topic, explore the full API Architecture guide.
System scale: APIs serving one or many clients (web, mobile, partners); from a few resources to many. Applies when you’re choosing between REST and GraphQL for a new or evolving API.
Team size: Backend and front-end; someone must own the API contract and (for GraphQL) the schema and resolvers. Works when the team can agree on resource design (REST) or schema design (GraphQL).
Time / budget pressure: Fits greenfield and “we have many clients with different data needs”; breaks down when the team has no GraphQL experience and must ship quickly—then REST is the safer default.
Technical constraints: .NET (ASP.NET Core); REST with JSON or GraphQL (HotChocolate, etc.). Browser and mobile clients; caching and tooling differ between REST and GraphQL.
Non-goals: This article does not optimise for gRPC or other styles; it focuses on REST vs GraphQL and when to choose which.
What is a REST API?
REST (Representational State Transfer) is an architectural style for APIs. You expose resources as URLs (e.g. /api/orders, /api/orders/123) and use HTTP methods to operate on them:
Method
Purpose
Example
GET
Read resource(s)
GET /api/orders
POST
Create resource
POST /api/orders
PUT
Replace resource
PUT /api/orders/123
PATCH
Update resource (partial)
PATCH /api/orders/123
DELETE
Delete resource
DELETE /api/orders/123
Responses are typically JSON. The response shape is fixed per endpoint—the client gets whatever fields the server returns.
Key characteristics:
Multiple endpoints (one per resource)
Fixed response shape per endpoint
HTTP caching works well (GET requests)
Versioning via URL (/api/v1/orders) or header
Widely supported by tools and developers
What is GraphQL?
GraphQL is a query language and runtime for APIs. Instead of multiple endpoints, you have one endpoint (e.g. /graphql). The client sends a query specifying exactly which fields it wants.
# Client queryquery{
order(id:123){
id
status
customer {
name
email
}}}
// Server returns exactly what was requested{"data":{"order":{"id":123,"status":"Shipped","customer":{"name":"John Doe","email":"john@example.com"}}}}
Key characteristics:
Single endpoint
Client defines the response shape (no over-fetching)
Nested queries (get related data in one request)
Strongly typed schema
Versioning by adding fields; deprecate old fields
REST vs GraphQL: comparison table
Aspect
REST
GraphQL
Endpoints
Multiple (one per resource)
Single (/graphql)
Response shape
Fixed by server
Defined by client
Over-fetching
Yes (get all fields)
No (get only requested)
Under-fetching
Yes (multiple requests)
No (nested queries)
Caching
HTTP caching works
Needs normalised cache
Versioning
URL or header
Add fields; deprecate
Learning curve
Low
Medium
Tooling
Broad (OpenAPI, Postman)
Growing (Apollo, Relay)
N+1 problem
Rare
Common (use DataLoader)
REST: strengths and weaknesses
Strengths
Simplicity. REST is straightforward: resources as URLs, HTTP methods, JSON. Most developers know it.
HTTP caching. GET requests are cacheable at HTTP level (CDN, browser). Add Cache-Control headers.
Tooling. OpenAPI/Swagger generates docs, client SDKs, and mock servers.
Weaknesses
Over-fetching. The endpoint returns all fields, even if client needs only a few.
Under-fetching. To get related data, client makes multiple requests.
Versioning. Changing shape requires a new version or breaking clients.
GraphQL: strengths and weaknesses
Strengths
No over-fetching. Client requests exactly the fields it needs.
No under-fetching. Nested queries fetch related data in one request.
Over-fetching is a real problem (mobile on slow networks)
Under-fetching causes too many round-trips
You can invest in DataLoader and resolver auth
Enterprise best practices
1. REST: use OpenAPI/Swagger. Generate docs, SDKs, and validate requests.
2. GraphQL: limit query depth and cost. Prevent abuse.
3. GraphQL: use DataLoader. Batch database calls to avoid N+1.
4. Both: authorise at the right level. REST: controller. GraphQL: resolver.
5. Both: monitor and trace. Use OpenTelemetry. Track latency and errors.
Common issues
Issue
REST
GraphQL
Over-fetching
Common
Solved
Under-fetching
Common
Solved
N+1 queries
Rare
Common (use DataLoader)
Caching
HTTP works
Needs normalised cache
Auth per field
No
Required
You can also explore more patterns in the API Architecture resource page.
Summary
REST is simple, cacheable, and widely supported—it fits most cases; GraphQL shines when you have many clients with different data needs and want to reduce over-fetching. For most .NET shops, adding GraphQL before that pain is real adds schema and tooling complexity without clear payoff. Next, map your clients and their data shapes; if over-fetching or versioning pain is significant, prototype GraphQL; otherwise stay with REST and refine your resource design.
Position & Rationale
I use REST as the default for most APIs—simple resources, HTTP caching, and broad tooling. I use GraphQL when we have multiple clients (web, mobile, partners) with genuinely different shapes of data and over-fetching or under-fetching is a real pain; then a single endpoint and client-defined queries can pay off. I avoid GraphQL when the team has no experience and the main ask is “modern API”—REST is enough for many cases. I prefer REST first; add GraphQL only when we have a clear need (e.g. mobile needs fewer fields, web needs more, and we don’t want to maintain multiple REST endpoints). I don’t choose GraphQL for “flexibility” alone if we have one client and stable requirements; the complexity (N+1, caching, auth per field) may not be worth it.
Trade-Offs & Failure Modes
REST sacrifices fine-grained client control over response shape; you gain simplicity, HTTP caching, and wide support. GraphQL sacrifices HTTP caching and simple mental model; you gain one endpoint and client-specified fields. N+1 in GraphQL is common without DataLoader; auth per field can get complex. Failure modes: adopting GraphQL without a clear multi-client or over-fetching problem; ignoring N+1 in GraphQL resolvers; no caching strategy for GraphQL.
What Most Guides Miss
Most guides compare REST vs GraphQL on features but don’t stress that client diversity is the main driver—one client and one shape → REST is simpler; many clients with different needs → GraphQL can help. Another gap: N+1 in GraphQL is the first production bug for many teams; use DataLoader or batch resolvers from day one. Caching for GraphQL is harder than REST (no HTTP cache by URL); you need a normalised cache or query-level cache.
Decision Framework
If one or few clients, stable resource shape → REST; use resources and HTTP methods; cache by URL.
If many clients with different data needs and over/under-fetching is painful → Consider GraphQL; design schema and use DataLoader for N+1.
For most .NET teams → Start with REST; add GraphQL only when the pain (multiple endpoints, versioning, client-specific shapes) justifies the complexity.
For GraphQL → Use DataLoader (or equivalent) to batch and avoid N+1; plan auth and caching.
For REST → Version the API (URL or header); use DTOs and avoid over-exposing.
Key Takeaways
REST = default for most APIs; simple, cacheable, widely supported.
GraphQL = when many clients need different shapes; one endpoint, client-defined queries; watch for N+1 and caching.
Start with REST; add GraphQL when over-fetching or multi-client pain is real.
For GraphQL: DataLoader for N+1; plan auth per field and caching.
If you’re building or modernizing API platforms, I provide API architecture consulting covering API-first design, governance, and integration strategy.
When I Would Use This Again — and When I Wouldn’t
I’d use REST again for most APIs—especially when we have one or a few clients and stable resource shapes. I’d use GraphQL again when we have multiple clients with genuinely different data needs and we’re willing to invest in schema, resolvers, DataLoader, and caching. I wouldn’t choose GraphQL “because it’s flexible” without a concrete over-fetching or multi-client problem. I also wouldn’t adopt GraphQL without addressing N+1 from the start (DataLoader or batching).
Frequently Asked Questions
Frequently Asked Questions
What is a REST API?
A REST API exposes resources as URLs and uses HTTP methods (GET, POST, PUT, DELETE). Responses are JSON. The shape is fixed per endpoint.
What is GraphQL?
GraphQL is a query language. The client specifies which fields it wants; the server returns only those fields. Single endpoint, no over-fetching.
What is over-fetching?
When the API returns more data than the client needs. REST endpoints return all fields; GraphQL lets client specify.
What is under-fetching?
When the client needs multiple requests to get all data. GraphQL solves this with nested queries.
What is the N+1 problem?
If a resolver fetches data for each parent, you get N+1 database queries. Use DataLoader to batch.
How do I cache GraphQL?
HTTP caching does not work. Use normalised cache (Apollo Client) or persisted queries.
How do I version REST?
URL versioning (/api/v1/orders) or header (Api-Version: 1). Deprecate old versions.
How do I version GraphQL?
Add new fields (non-breaking). Mark old fields as @deprecated. No URL versioning.
Can I use both together?
Yes. REST for simple CRUD, GraphQL for complex queries. Or BFF that calls REST and exposes GraphQL.
Which has better tooling?
REST has broader tooling (OpenAPI, Postman). GraphQL tooling is growing (Apollo, Relay).
Is GraphQL faster?
Not inherently. It can reduce round-trips but each request may be more complex.
When should I not use GraphQL?
When clients are simple, data needs predictable, and you want HTTP caching.
How do I authorise in GraphQL?
At the resolver level. Check permissions before returning data.
What is Hot Chocolate?
A GraphQL server for .NET. Schema-first or code-first, with ASP.NET Core integration.
What is Apollo?
A GraphQL platform with client (React, iOS, Android) and server (Node.js). Caching, dev tools, managed cloud.
Related Guides & Resources
Explore the matching guide, related services, and more articles.