Daniel Murillo
Index

Architecture · October 21, 2026 · Daniel Murillo

REST vs GraphQL: when you need flexibility

GraphQL does not replace REST in every case. When query flexibility adds value and what operational cost it implies.

GraphQL does not exist to replace REST in every case. It exists to solve a concrete problem: allowing the client to describe the data it needs within a defined schema.

Introduction

A mobile screen may need three fields from a resource, while an admin panel requires relationships, statistics, and additional details. With REST, these needs are usually solved through endpoints, filters, and projections. GraphQL offers another approach: the client writes a query and selects the fields it wants to receive.

Flexibility is valuable, but not free. GraphQL introduces a schema, resolvers, complexity policies, and a different caching strategy. Choosing between REST and GraphQL means evaluating the balance between flexibility, simplicity, performance, and operations.

1. How REST thinks

REST usually organizes the API around resources:

GET /api/products/123
GET /api/products/123/reviews
GET /api/products/123/inventory

This model is easy to understand, document, protect, and store in cache via HTTP, especially when responses are identifiable GETs with appropriate cache policies.

The difficulty appears when a screen needs to combine information from many resources. The client may make several requests, or the backend may offer a composite endpoint designed for that view.

2. How GraphQL thinks

GraphQL exposes a schema and lets the client request the fields it needs:

query ProductDetails {
  product(id: "123") {
    id
    name
    price
    reviews {
      rating
    }
  }
}

The response contains the requested structure. This can reduce transfer of unnecessary fields and make it easier for different clients to consume different data without creating an endpoint for every combination.

However, GraphQL does not eliminate server work. Each field can trigger resolution logic and database queries. A single HTTP request can end up more expensive than several simple REST requests.

3. The N+1 problem and DataLoader

Imagine a query requests a hundred orders and the customer of each order. If the resolver runs an individual query per customer, the request can generate more than a hundred database queries.

DataLoader and batching techniques let you group related data loads and reuse results within an operation.

It is also worth designing resolvers that leverage efficient queries, indexes, and result limits. GraphQL does not automatically make internal queries efficient.

4. Protecting the API from expensive queries

GraphQL’s flexibility can allow queries that are too deep or have very large lists. On a public API, it is worth considering:

  • Depth and complexity limits.
  • Maximum list size and pagination.
  • Timeouts and cancellation.
  • Appropriate authorization for the requested data.
  • Concurrency limits.
  • Persisted queries when useful.
  • Metrics per operation and resolver.

Not all queries have the same cost. Counting only the number of HTTP requests can hide the real work the server performs.

5. Cache: a different model

In REST, a GET URL and its headers can serve as a natural identity for a cacheable response. In GraphQL, several queries can ask for different combinations of fields and variables, so caching requires more design.

Common strategies:

  • Normalized entity cache on the client.
  • Resolver result cache.
  • Persisted queries.
  • HTTP cache for compatible operations.
  • Correct identification of variables, permissions, and user context.

GraphQL queries sent via GET can benefit from HTTP cache if the implementation allows it. Mutations must not be executed via GET.

The cache must avoid mixing results from users with different permissions and have a coherent invalidation strategy.

6. Compression and response size

GraphQL responses are usually JSON and can be compressed with Gzip or Brotli when the client and infrastructure support it. But if the response is already small, compression may not help much. If the server is CPU-bound, an aggressive level can worsen latency.

Field selection reduces unnecessary data; compression reduces the remaining bytes. They are complementary techniques, not substitutes.

7. Is GraphQL faster than REST?

Not necessarily. It can reduce network round trips and excess data in complex interfaces. It can also produce expensive queries, make conventional HTTP caching harder, and add resolution work.

REST can offer composite endpoints, projections, and efficient HTTP cache. A well-designed REST implementation can be simpler and faster for stable operations.

The comparison must measure the full operation: requests, database work, serialization, bytes transmitted, CPU, and p95/p99 latencies.

8. When to choose each one

Prefer REST when:

  • Resources and operations are relatively stable.
  • The API is public or integrates with many systems.
  • Conventional HTTP cache is important.
  • Operational simplicity and ease of debugging are priorities.
  • Most clients need similar data structures.

Consider GraphQL when:

  • Web, mobile, and other clients need different field combinations.
  • Screens aggregate data from several entities.
  • Flexibility significantly reduces unnecessary requests or data.
  • The team can operate a schema, control complexity, and observe resolvers.

It is also possible to combine both: REST for simple operations or public integrations and GraphQL for a client-oriented query layer. The decision should answer the domain and real needs, not a fashion preference.

Conclusion

GraphQL exists to give flexibility to data queries. That flexibility can simplify clients and reduce unnecessary transfer, but it needs limits, efficient resolvers, and a caching strategy.

REST remains an excellent option when the resource model is clear and HTTP capabilities offer a simple solution.

Choose GraphQL when query flexibility solves a real problem. Do not adopt it only because a single request looks more elegant than several.

In this series

  1. REST: how to design and optimize an API
  2. REST vs GraphQL (this note)
  3. gRPC vs REST
  4. WebSockets, SSE, and Webhooks
  5. Cache and compression
  6. Benchmarks and architecture decisions

References