SyncTrix logoSyncTrix
All articles
Platform10 min read

GraphQL vs REST: choosing based on your clients, not your preferences

GraphQL solves a specific problem with a real operational cost. Here's when that trade pays and when REST with good design is the better engineering decision.

By Lena Voss
GraphQL vs REST: choosing based on your clients, not your preferences

GraphQL is frequently adopted because it is modern and abandoned because it is complicated, with neither decision grounded in the problem it exists to solve. That problem is specific: many diverse clients needing different shapes of the same data, where the API team cannot keep pace with their requirements. If you do not have that problem, GraphQL is mostly cost.

01The problem GraphQL solves

With REST, the server decides response shape. A mobile client needing three fields from a resource that returns forty downloads all forty. A screen composing data from four resources makes four round trips. The fixes - custom endpoints per view, expansion parameters, sparse fieldsets - work but multiply endpoints and put the API team in the critical path of every client change.

GraphQL inverts this: the client specifies exactly what it needs in one request. When you have web, iOS, Android and partner integrations all wanting different projections and iterating at different speeds, that decoupling is genuinely valuable and hard to replicate.

02The costs are real and mostly operational

HTTP caching largely stops working. REST responses cache at the CDN by URL; GraphQL queries typically POST to one endpoint with the query in the body, so edge caching requires persisted queries or a specialised layer. For read-heavy public content this is a significant loss.

Observability changes shape too. Every request hits the same endpoint, so per-endpoint latency and error metrics become meaningless without per-resolver instrumentation. Rate limiting by request count stops being meaningful, since one query can be arbitrarily expensive. Each of these has a solution, and each is work that REST simply does not require.

DimensionRESTGraphQL
Client flexibilityServer-defined shapesClient-specified projections
HTTP cachingNatural, by URLNeeds persisted queries or extra layer
Over-fetchingCommon without extra designLargely eliminated
Round tripsMultiple for composed viewsSingle request
MonitoringPer endpoint, straightforwardPer resolver, needs instrumentation
Rate limitingRequest counts workNeeds cost analysis
Learning curveUniversally understoodSchema, resolvers, tooling
Trade-offs

03N+1 is the defining operational hazard

A query requesting fifty posts with their authors will, in a naive implementation, execute one query for posts and fifty for authors. Nested a level deeper and it multiplies again. The client wrote one innocent-looking query and the database received hundreds.

Batching with a data loader pattern is the standard mitigation and it is mandatory rather than optional - collecting identifiers within a tick and issuing one batched query per level. Any GraphQL server without this will fall over under real usage, and it is the most common cause of GraphQL performing worse than the REST API it replaced.

04You must bound query cost

In REST the server defines the work each endpoint performs. In GraphQL the client composes it, which means a deeply nested or wide query can be extraordinarily expensive - and this is reachable accidentally by a well-meaning client as easily as deliberately by an attacker.

Three controls are needed together: maximum query depth, complexity scoring that assigns cost per field and rejects queries above a budget, and pagination enforced on every list rather than optional. For public APIs, persisted queries - where clients may only execute pre-registered queries - remove the problem entirely at the cost of client flexibility, which is often the right trade for an external API.

  • Enforce maximum depth on every query.
  • Score complexity per field and reject over-budget queries.
  • Require pagination on lists; never allow unbounded collections.
  • Consider persisted queries for public or partner-facing APIs.

05A reasonable default

If you have one or two clients built by the same organisation that builds the API, REST with well-designed resources is simpler, faster to build and easier to operate. Most internal APIs and most early-stage products fall here, and adopting GraphQL is paying for flexibility that nobody will use.

If you have many diverse clients on independent release cycles, or partners whose requirements you cannot anticipate, GraphQL's decoupling earns its cost. A middle option worth more consideration than it gets is a backend-for-frontend: a thin REST layer per client type, composing internal services into exactly the shapes that client needs. It captures much of the benefit without the operational surface.

Topics

graphql vs restapi designn+1 queryapi gatewaybackend for frontendschema design

Lena Voss

Lead Architect · SyncTrix

Writes about the engineering decisions behind production systems - architecture, delivery and the trade-offs that only show up at scale.

Building something like this?

SyncTrix engineers AI, SaaS, platform and cloud systems for enterprises and high-growth teams. Tell us what you're shipping and we'll scope it with you.