From REST to GraphQL: When the Migration is Actually Worth It
BackendNode.jsAPI

From REST to GraphQL: When the Migration is Actually Worth It

Migrated 4 client APIs from REST to GraphQL and back from 2 of them. Here's when GraphQL pays off and when REST is still the right answer in 2026.

HJ
Hassan Javed
March 2026
10 min read

The honest summary

I've migrated four production APIs from REST to GraphQL over the last two years. I've migrated two of them back. The other two are still GraphQL and serving real users.

The pattern: GraphQL is genuinely better for some use cases and genuinely worse for others. The discourse online overstates both sides.

Here's the framework I use to decide, with the two migrations I regretted as concrete examples.

When GraphQL is worth it

Client-driven data needs

If your frontend regularly needs different shapes of the same data (mobile shows compact list, web shows expanded cards, dashboard needs aggregates), REST forces you to either over-fetch (large payloads) or proliferate endpoints (/users, /users-summary, /users-with-orders, etc.).

GraphQL lets the client ask for exactly what it needs in one query. Bandwidth drops, endpoint count stops growing.

This is the strongest case for GraphQL and the one I see win in production.

Multiple consumers with different needs

iOS, Android, web, and a third-party integration partner all consume your API. REST means versioning hell — change the API, break a consumer. GraphQL means each consumer queries what they need, schema changes are mostly additive.

Strongly typed frontend code

GraphQL Code Generator (or Apollo's tooling) gives you TypeScript types for every query result automatically. Your React components are fully typed end-to-end, no manual type definitions. This is a real DX win on TypeScript codebases.

Relationship-heavy data fetching

If your screens regularly need "user to orders to line items to product to category" (5 hops), REST means 5 round-trips or one custom endpoint. GraphQL resolves it in one query with a server-side join strategy.

When REST is still right

Public APIs with documentation requirements

REST plus OpenAPI spec is the standard for public APIs that third parties consume. Stripe, Twilio, GitHub — all REST. The tooling, mental model, and documentation ecosystem are unmatched.

Simple CRUD APIs

If your API is "list X, create X, update X, delete X" for half a dozen resources, GraphQL adds ceremony without value. REST is faster to write and faster to reason about.

Caching at the HTTP layer

REST GET requests are trivially CDN-cacheable. Add Cache-Control headers, point Cloudflare at the origin, done. GraphQL caching is possible (persisted queries plus GET) but harder to set up and maintain.

Teams without GraphQL fluency

GraphQL has a real learning curve — resolvers, DataLoader for N+1 prevention, schema design, error handling conventions. A team that hasn't shipped GraphQL before will move slower for the first 6 months.

File uploads, streaming, webhooks

GraphQL handles these awkwardly. File uploads need multipart extensions, streaming needs subscriptions or SSE, webhooks are flat-out REST. If your API is heavy on these, REST is the right answer.

The two migrations I regretted

Regret 1: B2B SaaS with simple CRUD

Migrated a B2B SaaS API from REST to GraphQL because "modern stack." The data model was 8 resources with simple CRUD. Frontend was one web app.

Six months later, the team had an Apollo Server with ~200 lines of resolver boilerplate, custom DataLoader instances for every relationship, a frontend that was no faster than the REST version, and two engineers complaining the GraphQL setup was "more annoying than helpful."

Migrated back to REST in three weeks. Codebase shrunk 30 percent. Velocity went up.

Lesson: GraphQL's win is in heterogeneous consumer needs. If you have one frontend and simple CRUD, REST is faster.

Regret 2: Public API with rate limiting

Built a Web3 indexer API in GraphQL. Customers integrated against it.

Problem: rate limiting GraphQL is hard. A single query can fetch a list of 1000 items with 5 nested fields each. A REST GET items with limit=10 is naturally constrained. GraphQL queries can request arbitrary depth and breadth.

We ended up implementing query complexity analysis (depth limits, field limits, custom cost scoring). Worked, but took 3 weeks and adds maintenance burden.

Lesson: Public APIs are easier to safely rate-limit when they're REST.

The hybrid pattern

A pattern I now use on most projects: REST for the API surface, GraphQL for one specific use case where it shines.

Example: a SaaS dashboard's "build a custom widget" feature needs flexible queries. The widget builder talks GraphQL to a specific endpoint. The rest of the app uses REST.

You get the best of both: REST simplicity for normal CRUD, GraphQL flexibility where you need it.

My default in 2026

REST plus OpenAPI for new APIs unless I have a specific reason for GraphQL
GraphQL when the frontend story is genuinely complex (mobile plus web plus partners plus flexible queries)
Hybrid for SaaS with one or two flexible-query features

TL;DR

GraphQL wins for heterogeneous consumers, relationship-heavy reads, type-safe frontends
REST wins for public APIs, simple CRUD, HTTP-layer caching, files or streaming
Don't migrate for "modern stack" reasons. Migrate for specific friction you're feeling.
Hybrid (REST plus targeted GraphQL) is often the right answer

If you're evaluating REST vs GraphQL for a project and want a second opinion before committing, contact me.

Related Reads

You might also like