GraphQL vs. REST: A Technical Comparison With Historical Context
Introduction
The conversation about how applications should request and receive data from servers has been dominated for the past decade by two paradigms: REST and GraphQL. REST, formalized by Roy Fielding in 2000, became the default architectural style for web APIs and remains the foundation of most public-facing interfaces in production today. GraphQL, developed internally at Facebook in 2012 and open-sourced in 2015, introduced a fundamentally different model in which the client, rather than the server, determines the shape of the response (Fielding, 2000; Engineering at Meta, 2015).
The two are not interchangeable solutions to the same problem. They emerged from different contexts, optimize for different constraints, and impose different costs on the teams that implement them. REST was born from the need to standardize communication across the entire World Wide Web. GraphQL was born from a specific crisis: Facebook's mobile application was crashing, and the existing API architecture could not deliver the data that native iOS views required without unacceptable overhead (Postman Blog, 2023).
This paper traces the origins of each paradigm, examines the specific technical trade-offs between them, documents how major companies have adopted one or both, and provides an evidence-based framework for deciding which approach fits a given set of requirements.
I. The Problem That Created GraphQL
In 2011, Facebook had a mobile problem. The company's iOS and Android applications were thin wrappers around views of the mobile website, rendered in HTML5 inside web views. As Facebook's user base grew and the complexity of the News Feed increased, this approach broke down. The apps suffered from poor performance, high network usage, and frequent crashes. Facebook's leadership made the strategic decision to rebuild the iOS application from scratch as a fully native app (Engineering at Meta, 2015; Hygraph, 2025).
That decision created a new technical requirement. The News Feed had previously been delivered as fully rendered HTML from the server. A native iOS application needed raw data instead: structured objects that iOS developers could use to render custom views. The existing API infrastructure was not designed for this. Facebook's internal RESTful API, built around 2009, had been created for a small number of third-party integrators, not for the complex data requirements of the News Feed. The company also had an internal query language called FQL (Facebook Query Language), modeled on SQL, but it required specialized expertise to optimize and did not map naturally to the hierarchical, recursive structure of News Feed data (Mulesoft, n.d.; Postman Blog, 2023).
The core difficulty was that a single News Feed story was not a simple object. Stories could contain shares of other stories, which themselves could contain shares. Comments, reactions, and author information were all interconnected in a recursive graph structure. Expressing this data through traditional REST endpoints meant either making dozens of sequential requests (one for each related resource) or building custom, denormalized endpoints that returned bloated payloads containing far more data than any single view required (Postman Blog, 2023; InfoQ, 2015).
Nick Schrock, a Facebook engineer, wrote the first prototype of a solution. He reasoned that instead of forcing the graph-structured News Feed data into a relational or resource-oriented model, the API itself should be a graph. He called the prototype "SuperGraph" and posted the code internally for review. Lee Byron joined the project, drawn to its approach, followed by iOS engineer Jonathan Dan and News Feed domain expert Dan Schafer. Together, they developed what would become GraphQL and shipped it into production powering the Facebook iOS News Feed in the summer of 2012 (Postman Blog, 2023; Mulesoft, n.d.).
Facebook used GraphQL internally for three years before open-sourcing it. By 2015, when the specification and a JavaScript reference implementation were released publicly, GraphQL was handling hundreds of billions of API calls per day across nearly the entire surface area of Facebook's mobile applications. It was not a theoretical exercise or an academic proposal. It was battle-tested infrastructure operating at a scale that few systems in the world have matched (Engineering at Meta, 2015).
II. How GraphQL Differs from REST Architecturally
The fundamental architectural difference between REST and GraphQL is in who controls the shape of the response. In a REST API, the server defines what data each endpoint returns. A request to GET /users/123 returns a fixed set of fields determined by the server's implementation. If the client needs additional related data, such as the user's recent orders, it must make a separate request to a different endpoint, such as GET /users/123/orders. If the client only needs two fields from a response that contains twenty, the other eighteen fields are still transmitted (LogRocket, 2025; Postman Blog, 2025).
In GraphQL, the client sends a query that specifies exactly what data it needs, including nested relationships, in a single request to a single endpoint. The server returns a JSON response that matches the exact shape of the query. If the client needs only a user's name and email, it requests only those fields. If it also needs the user's three most recent orders with their totals, it includes that in the same query. There is no over-fetching (receiving unnecessary data) and no under-fetching (needing to make additional requests for related data) (Hygraph, 2025; Engineering at Meta, 2015).
Single Endpoint vs. Multiple Endpoints
A REST API typically exposes many endpoints, each representing a specific resource or collection: /users, /users/{id}, /users/{id}/orders, /products, and so on. The number of endpoints grows as the data model grows. A GraphQL API exposes a single endpoint (conventionally /graphql), and the client's query determines what data is returned. The routing logic that REST distributes across many URL paths is replaced by schema resolution logic on the server (GitHub Docs, n.d.; Postman Blog, 2025).
Type System and Schema
GraphQL is built on a strongly typed schema that defines every type, field, and relationship available in the API. This schema serves as both a contract between client and server and as automatic documentation. Clients can introspect the schema at runtime to discover what queries are possible, what fields are available on each type, and what arguments each field accepts. REST APIs have no built-in equivalent to this. Tools like OpenAPI (Swagger) can provide similar documentation, but they are external specifications layered on top of the API rather than inherent to its design (Hygraph, 2025; GitHub Docs, n.d.).
Versioning
REST APIs typically handle breaking changes through explicit versioning: /v1/users becomes /v2/users when the response structure changes in a backwards-incompatible way. GraphQL takes a different approach. Because clients specify the exact fields they need, new fields can be added to the schema without affecting existing clients. Deprecated fields can be marked with a @deprecated directive and eventually removed once clients have migrated. Facebook's engineering team reported that they supported three years of released application versions on the same version of their GraphQL API without needing a version number (Engineering at Meta, 2015; Postman Blog, 2025).
III. Industry Adoption: Who Chose GraphQL and Why
GitHub
GitHub's adoption of GraphQL in 2016 was a pivotal moment for the technology's credibility. For years, GitHub's REST API had been held up as one of the best-designed REST APIs in the industry, and many companies had modeled their own APIs after it. When GitHub announced at its Universe conference that it was building a new API (v4) on GraphQL, it signaled that even organizations with excellent REST APIs had encountered limitations that GraphQL could address (InfoQ, 2016; Apollo GraphQL Blog, 2016).
GitHub's engineering blog identified the core problem directly. Their REST API required multiple separate calls to assemble a complete view of a resource. Responses simultaneously contained too much data for some consumers and not enough for others. The company had many distinct types of integrators, from CI/CD systems to code review tools to mobile applications, and a fixed set of REST endpoints could not serve all of them efficiently without an ever-growing number of specialized endpoints (InfoQ, 2016; GitHub Docs, n.d.).
GitHub's internal work on the GraphQL API began in March 2016. By September, the team decided the interface was valuable enough to expose publicly. Key benefits they cited included built-in documentation through schema introspection, strong typing that reduced integration errors, and the elimination of the sync problem where new product features lagged behind in the API because REST endpoints had to be manually created and maintained (Explore GraphQL, n.d.).
A migration study published by researchers analyzing GitHub's REST-to-GraphQL transition measured the impact on data transfer. On the median, REST responses contained 93.5 fields, while equivalent GraphQL queries requested only 5.5 fields, a 94% reduction. In terms of bytes transferred, the reduction went from 9.8 MB (REST) to 86 KB (GraphQL) for the same set of operations (Brito et al., 2019).
Shopify
Shopify adopted GraphQL as the foundation of its public API for third-party developers and its internal Storefront API. The rationale aligned with GitHub's: Shopify's data model is deeply interconnected (products have variants, which have inventory levels, which belong to locations, which have fulfillment services), and expressing these relationships through REST endpoints created exactly the kind of over-fetching and under-fetching problems that GraphQL was designed to solve. Shopify's API now serves hundreds of thousands of developers building applications on its platform.
Companies That Stayed with REST
Not every major API provider adopted GraphQL. Stripe, widely regarded as having one of the best-designed APIs in the industry, has remained committed to REST. Twilio's public API is REST-based. AWS exposes its services through REST and, in some cases, proprietary protocols. The common thread among these companies is that their APIs tend to serve operations that map naturally to the resource-oriented, CRUD-style model that REST handles well: create a charge, send a message, provision a server. The recursive, graph-structured data relationships that motivated GraphQL at Facebook are less central to their use cases.
IV. The Technical Trade-offs
Caching
Caching is REST's structural advantage. Because REST APIs use standard HTTP methods and unique URLs for each resource, the entire HTTP caching infrastructure (browser caches, CDN edge nodes, reverse proxies) works automatically. A GET /users/123 response can be cached by URL, and a Cache-Control header tells every intermediary how long to store it. This is one of the six constraints Roy Fielding defined as foundational to REST, and it is deeply embedded in web infrastructure (Stellate, n.d.; Apollo GraphQL Blog, n.d.).
GraphQL does not benefit from HTTP caching in the same way. Because all queries are sent as POST requests to a single endpoint, and the query body determines the response, there is no URL-level differentiation for caches to work with. Client-side caching is handled differently: libraries like Apollo Client use a normalized cache that identifies objects by their type and ID, storing them in a local cache and updating them as new queries return fresh data. This approach is sophisticated and effective, but it requires a dedicated client library and does not benefit from the decades of HTTP caching infrastructure that REST leverages automatically (Stellate, n.d.; Apollo GraphQL Blog, n.d.).
There are workarounds. Persisted queries allow clients to register query documents on the server in advance, then reference them by hash rather than sending the full query text. This makes GET requests possible for known queries, re-enabling standard HTTP caching. But this is an optimization layered on top of GraphQL's default behavior, not a built-in feature of the architecture (GraphQL.org, n.d.).
The N+1 Problem
One of GraphQL's most discussed performance challenges is the N+1 query problem. When a client requests a list of items along with a related field on each item (for example, a list of blog posts with each post's author), a naive GraphQL resolver implementation will execute one database query to fetch the list of posts and then one additional query for each post's author. For a list of 100 posts, that produces 101 database queries (GraphQL.org, n.d.; Bessey, 2024).
The standard solution is a batching utility called DataLoader, originally developed at Facebook. DataLoader collects all the individual requests for related data within a single execution tick and batches them into a single database query. Instead of 100 individual queries for authors, DataLoader issues one query that retrieves all 100 authors at once. This approach is effective and well-documented, but it requires developers to understand the problem and implement the solution explicitly. In a REST API, the equivalent scenario is typically handled at the endpoint level, where the server developer has direct control over the query plan (GraphQL.org, n.d.; Medium, "The Dark Side of GraphQL," 2024).
Security and Query Complexity
GraphQL's flexibility introduces a security surface area that REST does not have. Because clients can construct arbitrary queries, a malicious or careless client can request deeply nested data that forces the server to execute an expensive chain of database operations. A query that requests users, each user's friends, each friend's friends, and each of those friends' posts can produce a combinatorial explosion of data retrieval (Medium, "The Dark Side of GraphQL," 2024; Bessey, 2024).
The mitigations are well-established: query depth limiting, query complexity analysis (assigning a cost to each field and rejecting queries that exceed a threshold), and rate limiting based on computed query cost rather than simple request counts. GitHub's GraphQL API implements all of these. But each mitigation is something the server team must implement and maintain, whereas REST APIs are inherently protected from this class of attack because the server controls what data each endpoint returns (Explore GraphQL, n.d.; LogRocket, 2025).
Error Handling
REST APIs use HTTP status codes to communicate the outcome of a request: 200 for success, 404 for a missing resource, 500 for a server error. These codes are understood by every HTTP client, intermediary, and monitoring system. GraphQL handles errors differently. A GraphQL response always returns a 200 HTTP status code (assuming the request was syntactically valid), and errors are included in an errors array within the JSON response body. This means that standard HTTP monitoring tools cannot distinguish between a successful response and one containing application-level errors without inspecting the response body (Stellate, "Caching REST vs. GraphQL," n.d.; LogRocket, 2025).
Tooling and Developer Experience
GraphQL's introspection capability creates a developer experience advantage that REST cannot match natively. Because the schema is queryable at runtime, tools like GraphiQL and Apollo Studio can provide autocomplete, inline documentation, and query validation in the browser. A developer can explore an entire API without consulting external documentation. REST APIs achieve similar outcomes through OpenAPI specifications and tools like Swagger UI, but these require the API provider to create and maintain a separate specification document that may drift from the actual implementation (GitHub Docs, n.d.; Hygraph, 2025).
V. Direct Comparison
| Dimension | REST | GraphQL |
|---|---|---|
| Endpoint structure | Multiple endpoints, one per resource | Single endpoint, queries determine response |
| Data fetching | Fixed response per endpoint; may over-fetch or under-fetch | Client specifies exact fields; no over-fetching |
| Caching | Built-in HTTP caching via URLs and headers | Requires client libraries or persisted queries |
| Type system | None built-in; optional via OpenAPI | Strongly typed schema with runtime introspection |
| Versioning | Explicit versions (URL path or header) | Schema evolution via field addition and deprecation |
| Error handling | HTTP status codes (4xx, 5xx) | Always 200; errors in response body |
| Security surface | Server-controlled per endpoint | Requires depth limiting, complexity analysis |
| Network requests | One per resource; may require chaining | Single request for complex, nested data |
| Learning curve | Low; uses standard HTTP conventions | Higher; requires schema, resolver, and tooling knowledge |
| Best fit | CRUD operations, public APIs, simple data models | Complex data graphs, multiple client types, mobile-first |
VI. The Case Against GraphQL
GraphQL's popularity has produced a counter-narrative among experienced practitioners who have deployed it in production and encountered its costs firsthand. A 2024 essay titled "Why, after 6 years, I'm over GraphQL" summarized many of these concerns. The author, a developer who had championed GraphQL early in its adoption cycle, argued that the flexibility that makes GraphQL attractive is exactly what makes it difficult to maintain at scale. Queries that cannot be predicted cannot be optimized. Data that changes with every request cannot be cached. Authorization logic that must be applied at the field level, rather than the endpoint level, creates performance problems that do not exist in REST architectures (Bessey, 2024).
The 2024 Apollo GraphQL survey provided quantitative support for some of these concerns. According to the survey, 56% of teams reported caching challenges with GraphQL, and 34% of poorly optimized implementations suffered from the N+1 query problem. These are not edge cases. They are structural consequences of the architecture's design choices (Medium, "Why GraphQL is probably wrong," 2025).
The criticism is not that GraphQL is a bad technology. It is that GraphQL's costs are frequently underestimated. Teams adopt it because they are excited by the developer experience of writing queries and exploring schemas, then discover later that the server-side complexity of resolvers, DataLoaders, authorization rules, query complexity limits, and caching infrastructure adds up to a significant engineering burden. For projects with simple data models, a small number of client types, or a team without deep GraphQL expertise, a well-designed REST API with OpenAPI documentation and auto-generated client libraries can deliver equivalent value with substantially less operational overhead (Bessey, 2024; Perficient, 2024).
VII. When to Use Which
Choose REST when:
The data model maps naturally to discrete resources with CRUD operations. The API is public-facing and needs to be consumable by the widest possible range of clients without specialized tooling. Cacheability is a critical performance requirement. The team is small or does not have dedicated GraphQL infrastructure expertise. The primary consumers are server-to-server integrations rather than front-end applications with complex data requirements. Stripe's API is a clear example: charges, customers, subscriptions, and payouts are distinct resources that map perfectly to REST endpoints, and the API's cacheability and simplicity are core to its reputation (Postman Blog, 2025; Moesif, 2022).
Choose GraphQL when:
The data model is deeply interconnected with many relationships between types. Multiple client types (web, mobile, third-party integrators) need different subsets of the same data. The front-end team needs to iterate rapidly on data requirements without waiting for backend endpoint changes. Bandwidth efficiency matters, particularly for mobile clients on constrained networks. The engineering team has the expertise to implement and maintain the necessary server-side infrastructure, including resolvers, DataLoaders, query complexity analysis, and caching. GitHub's adoption is the canonical example: their data model (repositories, issues, pull requests, reviews, users, organizations) is deeply interconnected, and their integrator ecosystem has wildly diverse data requirements (InfoQ, 2016; GitHub Docs, n.d.).
Use both when:
Many organizations that have adopted GraphQL have not abandoned REST. The two are not mutually exclusive. A common pattern is to use GraphQL for the client-facing data layer (powering web and mobile applications) while maintaining REST APIs for public developer integrations, webhooks, and server-to-server communication. GitHub itself maintains both its REST API (v3) and its GraphQL API (v4) in production, and its engineering team has stated that they are actively backing the REST API with GraphQL internally (InfoQ, 2017). Shopify similarly offers both REST and GraphQL APIs to its developer ecosystem.
Conclusion
GraphQL and REST are not competitors in the way that their advocates sometimes frame them. They are tools designed for different categories of problems. REST emerged from the need to standardize communication across the entire web and remains the right choice for APIs where simplicity, cacheability, and universal compatibility are the primary requirements. GraphQL emerged from a specific problem at Facebook in which the existing API architecture could not deliver complex, interconnected data to mobile clients efficiently, and it remains the right choice for applications with those characteristics.
The mistake that organizations most commonly make is choosing a paradigm based on enthusiasm for its developer experience rather than a sober assessment of its operational costs. GraphQL's query language and schema introspection provide a genuinely superior development experience for front-end engineers. But that experience comes with a corresponding cost in server-side complexity, caching infrastructure, security hardening, and performance optimization. REST's simplicity may feel less exciting, but it leverages thirty years of HTTP infrastructure and requires substantially less custom engineering to operate at scale.
The engineers who designed GraphQL at Facebook understood this. They built it to solve a problem that their existing REST infrastructure could not solve, and they invested years of engineering effort into the server-side infrastructure needed to operate it reliably at their scale. Organizations considering GraphQL should ask not whether it is a better technology than REST in the abstract, but whether the specific problem they are trying to solve justifies the investment it requires.
Sources Cited
Apollo GraphQL Blog. "GraphQL Caching: The Elephant in the Room." https://www.apollographql.com/blog/graphql-caching-the-elephant-in-the-room
Apollo GraphQL Blog. "The GitHub GraphQL API." 2016. https://www.apollographql.com/blog/the-new-github-graphql-api-811b005d1b6e
Bessey, Matt. "Why, after 6 years, I'm over GraphQL." May 24, 2024. https://bessey.dev/blog/2024/05/24/why-im-over-graphql/
Brito, Gleison, Thais Mombach, and Marco Tulio Valente. "Migrating to GraphQL: A Practical Assessment." 2019. https://arxiv.org/pdf/1906.07535
Engineering at Meta. "GraphQL: A Data Query Language." September 14, 2015. https://engineering.fb.com/2015/09/14/core-infra/graphql-a-data-query-language/
Explore GraphQL. "Building a Better GitHub Platform with GraphQL." https://www.graphql.com/articles/graphql-at-github
Fielding, Roy Thomas. Architectural Styles and the Design of Network-based Software Architectures. Doctoral Dissertation, University of California, Irvine, 2000. https://ics.uci.edu/~fielding/pubs/dissertation/top.htm
GitHub Docs. "About the GraphQL API." https://docs.github.com/en/graphql/overview/about-the-graphql-api
GraphQL.org. "Performance." https://graphql.org/learn/performance/
Hygraph. "What Is GraphQL and How It Works." October 27, 2025. https://hygraph.com/learn/graphql
InfoQ. "Facebook Open Sources Data Query Language GraphQL." October 7, 2015. https://www.infoq.com/news/2015/10/graphql-your-schema/
InfoQ. "GitHub Adopts New GraphQL API." October 12, 2016. https://www.infoq.com/news/2016/10/graphQL-GitHub/
InfoQ. "GitHub GraphQL API Is Out of Early Access." June 8, 2017. https://www.infoq.com/news/2017/06/github-graphql-interview/
LogRocket Blog. "GraphQL vs. REST APIs: What's the Difference." March 6, 2025. https://blog.logrocket.com/graphql-vs-rest-api-why-you-shouldnt-use-graphql/
Medium. "The Dark Side of GraphQL: Hidden Pitfalls and Their Solutions." November 11, 2024. https://abubakardev0.medium.com/graphql-beyond-the-hype
Medium. "Why GraphQL Is Probably Wrong for Your Project." October 9, 2025. https://medium.com/@LoschCode/why-graphql-is-probably-wrong-for-your-project
Moesif Blog. "REST vs GraphQL APIs, the Good, the Bad, the Ugly." January 27, 2022. https://www.moesif.com/blog/technical/graphql/REST-vs-GraphQL-APIs-the-good-the-bad-the-ugly/
Mulesoft. "What Is GraphQL and How Did It Evolve from REST and Other API Technologies?" https://www.mulesoft.com/api-university/graphql-and-how-did-it-evolve-from-rest-api
Perficient. "GraphQL: Not an Ideal One!" March 6, 2024. https://blogs.perficient.com/2024/03/06/graphql-whats-wrong-with-it/
Postman Blog. "GraphQL vs REST." December 16, 2025. https://blog.postman.com/graphql-vs-rest/
Postman Blog. "What is GraphQL? Part 1: The Facebook Years." June 30, 2023. https://blog.postman.com/what-is-graphql-part-one-the-facebook-years/
Stellate. "Caching REST APIs vs. GraphQL APIs." https://stellate.co/blog/caching-rest-vs-graphql
Stellate. "GraphQL Performance: Key Challenges and Solutions." https://stellate.co/blog/graphql-performance-key-challenges-and-solutions