Understanding REST
GraphQL solves a real problem — over-fetching and the N+1 request pattern are genuinely painful at scale — but it also introduces real complexity that most small teams don't need. REST isn't obsolete; it's still the right default for most APIs. GraphQL earns its complexity when you have multiple clients with very different data needs, or a frontend team that needs to iterate faster than the backend can keep up.
# REST: Multiple requests to build a user profile page GET /api/users/123 # User data GET /api/users/123/posts # User's posts GET /api/users/123/followers # User's followers
REST APIs are intuitive because they map directly to HTTP semantics. GET retrieves, POST creates, PUT/PATCH updates, DELETE removes. URLs are bookmarkable and shareable. Caching works naturally through HTTP cache headers. Every developer already knows how HTTP works.
Understanding GraphQL
GraphQL is a query language for APIs, developed by Facebook in 2012 and open-sourced in 2015. Instead of multiple endpoints for different resources, GraphQL exposes a single endpoint and lets clients specify exactly what data they need in a structured query.
# GraphQL: One request to build the same user profile page query { user(id: "123") { name email posts(limit: 5) { title publishedAt } followers { count } } }
The server responds with exactly the fields requested — no more, no less. This single query replaces the three separate REST calls above.
The Problems GraphQL Solves
Over-fetching
With REST, an endpoint like GET /users/123 returns the entire user object — all fields, even those you don't need. If you only want the user's name for a display avatar, you still receive their email, address, preferences, and everything else. GraphQL lets you request only name and saves the bandwidth.
Under-fetching (N+1 Problem)
To display a list of posts with their authors' names, a REST API might require: one request to get posts, then one request per post to get each author. For 10 posts, that's 11 requests. GraphQL can fetch posts with nested author names in a single query, solving the N+1 problem at the query level.
Strong Typing and Introspection
GraphQL APIs have a strongly-typed schema that describes every type, field, and relationship. This schema is machine-readable, enabling auto-generated documentation, type-safe client code generation, and powerful IDE tooling. You always know exactly what data is available and its type.
Where REST Wins
Caching
HTTP caching is built for REST. GET requests to stable URLs can be cached at the browser, CDN, and reverse proxy level automatically. GraphQL typically uses POST requests for queries, making standard HTTP caching difficult. Persisted queries or specialized CDN configurations are needed to cache GraphQL responses.
Simplicity
REST requires no special client library — any HTTP client works. GraphQL requires either a client library (Apollo, urql, URQL) or careful manual implementation of the query protocol. For simple APIs, REST's simplicity is a significant advantage.
File Uploads
File uploads with GraphQL require the multipart request specification, which adds complexity. REST handles file uploads naturally with multipart/form-data. For APIs with significant file upload requirements, REST is easier.
Universal Tooling
REST can be consumed by any tool that speaks HTTP: curl, Postman, browser fetch, mobile apps, even wget. Every programming language has HTTP libraries. GraphQL clients, while widely available, add a dependency and learning curve.
Where GraphQL Wins
Complex, Interconnected Data
For applications with complex, deeply nested data models — social networks, e-commerce with products/variants/categories/reviews, content management systems — GraphQL's ability to query the graph of relationships in a single request is compelling.
Multiple Clients with Different Needs
If a mobile app, web app, and third-party integrations all consume the same API but need different data, REST requires building multiple endpoints or accepting over-fetching. GraphQL lets each client ask for exactly what it needs from the same schema.
Rapid Frontend Development
GraphQL puts API flexibility in the hands of frontend developers. Rather than waiting for backend engineers to build a new endpoint or add a field to an existing one, frontend developers can craft their own queries against the existing schema. This decouples frontend and backend development cycles.
Practical Decision Framework
- Choose REST if: You're building a simple CRUD API, need aggressive HTTP caching, your team is small and REST is familiar, or you're exposing a public API for third-party developers (REST is more universally understood).
- Choose GraphQL if: You have complex, interconnected data, multiple clients with different data needs, a large frontend team that wants flexibility, or you're building something like a marketplace or social platform with rich queries.
- Consider both: Many companies run both — GraphQL for their mobile and web clients, REST for simple third-party integrations and webhooks.
GraphQL can enable sloppy thinking by making it easy to expose everything in the schema without considering access patterns. N+1 database queries still happen server-side if not handled with DataLoader or similar batching solutions. GraphQL requires thoughtful schema design and resolver optimization, just like REST requires thoughtful endpoint design.
Conclusion
REST and GraphQL are both excellent choices when used appropriately. REST remains the right choice for most APIs — it's simple, universally understood, and HTTP caching works naturally. GraphQL shines for complex data graphs, multiple clients, and empowering frontend developers. The "right" answer depends on your team's expertise, your data model's complexity, and your clients' needs. Many successful products use both, choosing the right tool for each part of the system.