GraphQL vs REST — Which Is Better?
Which API design paradigm should you choose for your application? GraphQL or REST. This article looks at the pros and cons of each.
Join the DZone community and get the full member experience.
Join For FreeGraphQL and REST are two of the most popular API frameworks currently in use, with GraphQL seeing increasing adoption. GraphQL was developed by Facebook to address key challenges in REST APIs, particularly in reducing latency for mobile applications. The debate over which is better continues within the developer community, with strong arguments on both sides.
The choice between GraphQL or REST depends on the type of application being built. GraphQL addresses latency issues caused by over-fetching and under-fetching, and provides built-in support for real-time updates. On the other hand, REST leverages HTTP constructs for caching, rate control, and telemetry, allowing these concerns to be handled at the platform layer rather than the application layer.
Let’s explore the pros and cons of GraphQL and what an architect should evaluate when making a decision for their project.
GraphQL Pros
Avoidance of Data Over-Fetching/Under-Fetching
One of GraphQL’s biggest advantages is preventing over-fetching of data. In REST, a single API endpoint may return more data than needed for certain clients, especially in mobile applications with limited UI real estate.
This issue is typically addressed in REST using the Backend-for-Frontend (BFF) pattern, but there is no standard BFF framework. GraphQL allows clients to specify exactly which fields they need, preventing unnecessary data retrieval.
Example
- A web app might request a user’s name, address, and email.
- A mobile app might request only the user’s name to optimize bandwidth.
Benefit
Conserves bandwidth and reduces latency.
Reduced Latency
REST does not have a built-in orchestration layer, meaning a client might need to call multiple REST APIs to fetch all required data.
With GraphQL, a single endpoint can handle multiple entities at once, reducing network calls. GraphQL achieves this through GraphQL servers like Apollo Server, Hasura, and GraphQL Mesh, which resolve queries, orchestrate backend calls, and return a unified response. This could be achieved in REST via BFF pattern but there is no standard implementation available.
REST Example
A client fetching user data and order history would need:
/users/{id}→ Fetch user details/orders/{userId}→ Fetch order history
GraphQL Example
{
user(id: 1) {
name
email
orders {
orderId
totalPrice
}
}
}
Benefit
Reduces multiple network calls into a single request, lowering latency.
Real-Time Updates Subscriptions
One of the biggest pros of GraphQL is its support for real-time updates via subscriptions, allowing clients to receive automatic updates when data changes.
Example Use Cases
- Live stock market updates
- Chat applications
- Real-time notifications
GraphQL subscriptions typically use WebSockets, though alternatives like Server-Sent Events (SSE) and polling are also possible.
Benefit
Efficient real-time data handling, better than REST-based polling.
Decoupling of Frontend from Backend Implementation
GraphQL actors (e.g., clients, servers, resolvers) interact with data as an entity graph, vis-à-vis a REST API, which is based on structured endpoints. Thus, GraphQL enables higher decoupling of the frontend from the backend implementation.
Benefit
Frontend teams can evolve independently from backend teams without requiring backend API changes.
Versioning
In REST, API versioning (/v1/users, /v2/users) is required when changing or deprecating fields.
GraphQL eliminates versioning by marking deprecated fields without breaking existing clients:
type User {
id: ID!
name: String
email: String @deprecated(reason: “Use contactEmail instead”)
}
Benefit
Backend modifications do not force frontend updates.
GraphQL Cons
With that, let’s look at GraphQL's cons. One of the biggest issues is the impact on HTTP constructs which traditionally web applications have relied upon for cross cutting concerns like telemetry, caching, rate limiting and security.
Caching
REST leverages URL-based caching at the CDN, API Gateway, Reverse proxy and browser levels.
Example
You can have separate caching policies for following endpoints based on URL pattern, with the cache key being generated out of the URL Pattern and query param
/locations?city=NewYork/restaurants?category=Italian
GraphQL, however, uses a single endpoint, making traditional URL-based caching ineffective.
We could overcome this by using HTTP GET for queries (cannot use GET for mutations). Caching can then be governed based on query params. However, this approach can become very complex because there may be several variations of the query for the same entities, and even within the data properties of entities.
Without careful design, caching policy using this approach may become infeasible or less effective than in REST. In addition, developers must be careful not to use GET for large queries, as browsers enforce size limits on query parameters. This becomes a big challenge when an architect wants to decouple caching from one of the network layers (e.g., a CDN).
This issue can be partially resolved using GraphQL’s persisted queries. In persisted queries, the client passes a query ID rather than the whole query. This helps address query variability and the query param length issue. However, the GraphQL server now needs to store the client query schema, thus introducing a bit of coupling between frontend and backend.
Tools like Apollo GraphQL provide sophisticated caching capabilities at the client or server. But the CDN (edge) side caching challenge remains, even though Cloudflare and Akamai now offer better support for GraphQL caching. Furthermore, not all GraphQL implementations support HTTP GET and rely on POST for both queries and mutations, which renders this approach infeasible.
This could be overcome by sending query params (say the “operation name”) in a POST request, but that will make it a non-standard implementation and an anti-pattern.
Summary
Due to GraphQL’s single endpoint structure, caching must often be handled at the application level (client and server) rather than being delegated to platform layers like CDN or reverse proxies (e.g., NGINX), as is common in REST APIs.
Telemetry
REST relies on structured URLs (/users, /orders), making it easy to monitor performance per endpoint. Since GraphQL uses one endpoint (/graphql), API Gateways and CDNs cannot track performance per entity.
These stats need to be captured at the GraphQL application layer, and many telemetry tools now provide query-level insights. CDN tools like Akamai provide Telemetry for GraphQL by analyzing the operationName param in request. Persisted queries also enhance the Telemetry support. Yet fine-grained telemetry analysis, such as REST, is not possible in the CDN/Load Balancer/API Gateway layers.
Summary
GraphQL telemetry must be handled at the application level, unlike REST, where platform-level monitoring is possible.
Rate Limiting
Rate limiting can be done at CDN or API Gateway layer for specific REST APIs at the URL level. However, for GraphQL, rate limiting needs to be done based on query depth or complexity by GraphQL-aware Gateways like Apollo/Hasura; This approach is more complicated than REST, and once again, pushes this concern to the application layer.
REST APIs allow rate limiting per endpoint (/users limited to 1000 requests per hour), and this can be implemented either at the application layer or the platform layer (CDN, API Gateway).
GraphQL requires analysis of query complexity, as a single request can return vast amounts of data. Hence, rate limiting needs to be done based on query depth or complexity by GraphQL-aware Gateways like Apollo/Hasura, thus making it much more complicated than REST
Summary
GraphQL rate limiting requires more advanced logic and should be implemented at the application layer, where more options are available.
Limited Platform Support
Cloud and CDN support for GraphQL is getting stronger. However, there are still gaps. For example, AWS API Gateway does not support input validation for HTTP APIs (such as GraphQL) compared to REST APIs. AWS API Gateway does not support Resource policies for HTTP APIs for access control (for example, restrict access by IPs).
Summary
Platform support for GraphQL is growing but is more advanced for REST
Security
Poorly designed GraphQL applications can introduce several security vulnerabilities. Schema introspection exposes API details that malicious actors can use to mount attacks. Deep queries or query variations can cause Denial-of-Service (DoS) attacks by bypassing caching. This vulnerability can be mitigated by disabling introspection in Production. Strictly Persisted Queries offer the most secure solution, but introduce a level of coupling between frontend and backend
Authorization in REST can be implemented via endpoint-based authorization, and this can be done at the API Gateway or CDN layer. In GraphQL, this must be done at the application level to determine which queries in the request require authorization.
Summary
REST security can be enforced at platform layers (API Gateways and WAFs), but GraphQL requires resolver-level security and needs more careful design.
Error Handling
REST APIs return standard HTTP status codes:
200 OK→ Success404 Not Found→ Invalid request500 Internal Server Error→ Server issue
GraphQL always returns HTTP 200, even for errors, embedding error messages inside the response body rather than using standard HTTP status codes. This behavior requires additional handling in monitoring tools and client applications, which traditionally rely on HTTP status codes (404 Not Found, 500 Internal Server Error) to determine API failures.
{
“data”: null,
“errors”: [
{ “message”: “User not found”, “code”: “NOT_FOUND” }
]
}
Summary
Traditional HTTP-based monitoring tools need customization for GraphQL error handling.
Conclusion
There is no one-size-fits-all framework. GraphQL is a powerful API framework with multiple benefits:
- Frontend-backend decoupling
- Reduced latency for mobile applications and data-intensive web applications
- Resolution of API versioning issues
However, using GraphQL removes several of the REST framework’s advantages accrued from using HTTP constructs for caching/telemetry/security, which are typically handled at the platform level — CDN, Load Balancer, API Gateway, or Reverse Proxy — in REST. With GraphQL, these concerns often shift to the application layer, requiring additional effort from developers.
Use GraphQL If
- Your app requires complex or multi-entity data fetching
- You need real-time updates
- You want frontend flexibility & backend decoupling
Use REST If
- You need platform-level caching, telemetry, and security
- You want simpler rate limiting & security enforcement
- You require standard HTTP-based error handling
- Your app has moderate data requirements
Finally, for many projects, GraphQL and REST can coexist, allowing you to leverage the strengths of each.
Opinions expressed by DZone contributors are their own.
Comments