Every few years "GraphQL is going to replace REST" makes the rounds again, and every few years REST is still running most of the production APIs we integrate with. The truth is simpler than a rivalry: they solve different problems well, and the right choice depends on your clients, your data shape, and your team's operational maturity.
What REST still does better
- HTTP caching. REST's resource-based URLs map directly onto HTTP caching semantics — CDNs, browser caches, and reverse proxies all understand a GET request out of the box.
- Simplicity for simple contracts. If your API mostly serves a fixed set of well-known resources, REST's predictability is a feature, not a limitation.
- Tooling and familiarity. Every language, every monitoring tool, every API gateway has first-class REST support. Onboarding a new engineer takes an afternoon.
What GraphQL solves that REST doesn't
- Over-fetching and under-fetching. A mobile client that needs five fields from three resources can get exactly that in one request, instead of three round trips or a bloated response.
- Rapidly evolving frontends. When multiple client teams (web, iOS, Android) need different shapes of the same data, GraphQL lets each query for what it needs without backend changes.
- Strong typing end-to-end. A GraphQL schema is a contract that generates client types automatically, cutting down on an entire class of integration bugs.
The question isn't "which is more modern." It's "how many different clients need different shapes of my data, and how much do I rely on HTTP-layer caching."
A simple decision framework
- One primary client, well-known data shapes, heavy caching needs? REST, usually with a thin OpenAPI layer for documentation and client generation.
- Multiple client types with different data needs, evolving fast? GraphQL, with careful attention to query complexity limits and N+1 resolution.
- Public API consumed by third parties you don't control? REST — it's the format external developers expect and can debug with curl.
- Internal API powering your own apps with a small, trusted team? Either works; pick based on team familiarity.
Security and performance apply to both
Regardless of style, the fundamentals don't change: authenticate every request, rate-limit aggressively, validate input at the boundary, and never trust a client-supplied ID without an authorization check behind it. GraphQL adds its own wrinkle — query depth and complexity limits — since a poorly-bounded nested query can do more damage than a REST endpoint ever could in a single request.
Our default
For most client engagements, we start with REST — it's faster to stand up, easier to secure by default, and simpler to hand off. We reach for GraphQL specifically when a project has multiple frontends with genuinely different data needs, or when the client's roadmap makes it clear the API's consumers will keep multiplying.