GraphQL vs REST — When to Choose Each
Fast recall
Quick revision
Core answer
Whether you can match a real workload (mobile vs web, narrow reads vs nested graphs, public API vs internal) to GraphQL or REST, and explain the operational cost of each — caching, rate-limiting, schema governance.
Picking GraphQL because it is newer, then discovering that CDN caching, per-field authorization, and rate-limiting all get harder and over-fetch just moves server-side. Or picking REST for a highly nested mobile UI and shipping 6 round-trips where one GraphQL query would suffice.
Discuss query complexity analysis and cost-based rate limiting, persisted queries for cache-friendliness, GraphQL federation vs BFFs, and cases where hybrid (REST for writes + GraphQL for reads) outperforms either alone.
Interview-ready guide
Interview answer
GraphQL and REST are not simply alternatives — they solve different client-server coupling problems, and the right choice depends on who controls the data shape and how many distinct clients your API serves.
REST — fixed shapes, universal compatibility:
- The server defines fixed endpoints that return fixed shapes, which works well until you have a mobile app that needs three fields and a dashboard that needs forty from the same resource
- Unmatched operational simplicity: HTTP caching works natively through
GET+Cache-Control, curl and Postman work without configuration, and every CDN and load balancer understands the model - The default for external-facing APIs — partners and browsers can't install protobuf compilers or learn a custom query language; REST's universality is a real advantage
GraphQL — client-shaped queries:
- Lets clients specify exactly what they need in a query document; a single
/graphqlendpoint serves every consumer, eliminating endpoint proliferation for teams with diverse clients - For teams with three or more clients with divergent data needs, or stitching data from multiple backend services, GraphQL pays for itself within a sprint
- The flexibility comes at operational cost:
POST /graphqlbreaks HTTP caching natively, so you need persisted queries for edge caching; observability requires field-level instrumentation since every request hits the same URL
The critical trade-offs:
- Schema design mistakes are expensive — a field name you publish is a public contract that's harder to evolve than a REST endpoint; breaking schema changes require migration strategies
- The N+1 problem emerges immediately: each resolver runs independently with no knowledge of siblings, so 100 books with authors fires 101 queries unless you wire DataLoader batching from day one
I recommend REST for one frontend and simple CRUD, GraphQL when you have three or more clients with divergent needs or complex multi-source data. Most production systems run both — REST at the edge, GraphQL as an internal BFF.
GraphQL vs REST — When to Choose Each
Direct Answer
Choose GraphQL when clients need flexible data fetching, you have multiple client types with different data needs, or you want to reduce over-fetching and under-fetching. Choose REST when you need simplicity, caching via HTTP, file uploads, or when your API consumers expect standard HTTP conventions.
Code Example
# --- Scenario: a mobile screen shows a user, their last 5 orders,
# each with its line items and the product name/thumbnail. ---
# ============ REST (3+ round trips, over-fetch per call) =====================
# GET /users/42 -> User JSON with 40 fields
# GET /users/42/orders?limit=5 -> Array of 5 Order JSONs
# GET /orders/{id}/items (x5) -> 5 item arrays
# GET /products/{sku} (x N items) -> N product JSONs
# Many sequential/parallel requests; clients stitch on-device.
# ============ GraphQL (1 query, exactly what the UI needs) ===================
query OrderHistoryScreen($userId: ID!) {
user(id: $userId) {
id
displayName
avatarUrl
orders(last: 5) {
id
placedAt
total { amount currency }
items {
quantity
product {
sku
name
thumbnailUrl
}
}
}
}
}
# One round-trip; the server walks the graph, batching via DataLoader.
# The mobile client declares the exact field set needed for this screen.
# ============ gRPC (typed RPC, strong perf, not browser-native) ==============
# user_service.proto
syntax = "proto3";
package acme.user.v1;
service UserService {
rpc GetUserWithOrders (GetUserWithOrdersRequest)
returns (GetUserWithOrdersResponse);
}
message GetUserWithOrdersRequest { string user_id = 1; int32 last = 2; }
message GetUserWithOrdersResponse {
User user = 1;
repeated Order orders = 2;
}
# Fastest on the wire (protobuf + HTTP/2 multiplexing); best for service-to-service.
# Needs gRPC-Web + a proxy for browsers; tooling cost higher than REST.
# Spring-side resolver sketch for the GraphQL version:
@Controller
class OrderHistoryResolvers {
@QueryMapping
User user(@Argument String id) { return users.find(id); }
@SchemaMapping(typeName = "User", field = "orders")
List<Order> orders(User user, @Argument int last) {
return orderService.lastN(user.id(), last);
}
// Batched resolver for Product to avoid N+1 on items.product
@BatchMapping
Map<OrderItem, Product> product(List<OrderItem> items) {
List<String> skus = items.stream().map(OrderItem::sku).toList();
Map<String, Product> bySku = productService.getAll(skus);
return items.stream().collect(Collectors.toMap(i -> i, i -> bySku.get(i.sku())));
}
}
Common Mistakes & Pitfalls
Picking GraphQL because it is newer, then discovering that CDN caching, per-field authorization, and rate-limiting all get harder and over-fetch just moves server-side. Or picking REST for a highly nested mobile UI and shipping 6 round-trips where one GraphQL query would suffice.
Check your understanding
Answer these without looking back at the article.
- How would you handle versioning in a GraphQL API?
- What is a BFF (Backend for Frontend) pattern and how does GraphQL help there?
- How do you implement HTTP caching with GraphQL?
Related interview prep categories
1Want a guided curriculum order?
These modules are also sequenced in our flagship backend interview track — open it when you prefer an ordered path instead of browsing by topic.