This gets framed as a technology debate more often than it should be. It's really an operations question: who's calling your API, how often does the shape of the data they need change, and how much engineering time can you spend on API maintenance going forward. Answer those three honestly and the choice usually makes itself.

The decision matrix

Score your project against each row. Whichever column you land in more often is your answer.

Factor Lean REST Lean GraphQL
Number of client apps One or two, similar data needs Several — web, iOS, Android, each needing different slices of data
Team's API experience Team is new to building APIs Team has shipped GraphQL before, or has time to learn it properly
Caching needs Heavy reliance on HTTP/CDN caching Caching handled client-side (Apollo, Relay) or not critical yet
Data shape Resources map cleanly to simple endpoints Deeply nested, relational data where clients need different subsets
Third-party consumers External partners will integrate with your API API is primarily consumed by apps you control
Timeline Need to ship fast with a small team Have time to invest in schema design up front

Why each factor actually matters

Client count is the biggest signal

GraphQL's core advantage is letting each client request exactly the fields it needs in one round trip. That's a minor convenience with one client and a major win with five — a mobile app that needs a lean payload and a dashboard that needs a rich one can both query the same schema without you building separate endpoints or over-fetching data on the lighter client.

REST's caching story is genuinely simpler

REST endpoints map naturally to HTTP caching — CDNs, browser caches, and reverse proxies all understand GET requests to stable URLs out of the box. GraphQL typically uses a single POST endpoint, so you lose that free layer and need client-side caching (Apollo Client, Relay) or a dedicated caching layer to get equivalent performance. Not a blocker, but it's real engineering work REST gives you for free.

Third-party integrations favour REST

If external partners or customers will build against your API, REST's simplicity and the sheer volume of existing tooling, documentation habits, and developer familiarity lowers the integration friction. GraphQL is a steeper learning curve for someone integrating with you for the first time.

The "N+1 problem" is real and underestimated

GraphQL's flexibility means a naive resolver implementation can trigger a cascade of database queries per request — the classic N+1 problem. Solving it properly (DataLoader batching, query complexity analysis) is a real skill investment. Teams that skip this step ship a GraphQL API that's slower than the REST equivalent would have been.

A middle path: most teams don't need to choose exclusively

It's common — and often correct — to run REST for simple, cacheable, high-traffic reads (public content, static resource lookups) and GraphQL for the complex, client-varied parts of the product (a dashboard aggregating data from multiple sources). You don't have to pick one architecture for the entire system.

Our default recommendation

For a new product with one or two clients and a small team: start with REST. It's faster to ship, easier to debug, and has less operational surface area to maintain. Move to GraphQL when you can point to a specific, current pain — usually multiple clients with genuinely different data needs, or a mobile team burning bandwidth on over-fetched REST responses. Building GraphQL preemptively "because it's more modern" is the single most common mistake we see — it adds real complexity that only pays off once you've outgrown REST's simplicity.