All Articles
API Design8 min read5 October 2016

GraphQL vs REST: What the Hype Got Right and Wrong

Facebook open-sourced GraphQL in 2015. By 2016, the developer community had split into two camps. I was in the sceptical camp. Then I built something with it and changed my mind, partly.

GraphQLRESTAPI DesignBackend

Facebook had been using GraphQL internally since 2012 before they open-sourced it in 2015. By 2016, it had gathered enough momentum that you could not go to a frontend conference without hearing about it.

The core complaint GraphQL addresses about REST is real. With REST, the server defines what data each endpoint returns. The client takes what it gets. This leads to two related problems. Overfetching: the endpoint returns more data than the client needs. Underfetching: the client needs data from multiple endpoints and must make multiple round trips.

Both problems are expensive on mobile. More data means more bytes over the network. Multiple round trips add latency. Facebook built GraphQL to solve these specific problems for their mobile apps, and it worked.

The GraphQL approach flips the model. The client specifies exactly what fields it needs in a query. The server returns exactly those fields, nothing more. Multiple resources can be fetched in a single query. Nested relationships can be traversed in one request.

The type system is another genuine advantage. GraphQL schemas are strongly typed and self-documenting. Introspection means clients can discover the API automatically. Tooling like GraphiQL gave frontend developers an interactive explorer that REST APIs rarely matched.

So why was I initially sceptical?

The operational complexity is real. Caching REST responses is straightforward: URL is the cache key, HTTP headers control expiry. Caching GraphQL responses is harder because every query is a POST to the same endpoint. Persisted queries help but add complexity. HTTP caching, which is essentially free with REST, requires deliberate engineering with GraphQL.

N+1 query problems require the DataLoader pattern to solve. Without it, a GraphQL resolver naively might issue one database query per item in a list. With hundreds of items, this is catastrophic. DataLoader batches these, but it is another concept developers have to learn and implement correctly.

Error handling in GraphQL is also different from REST in ways that catch people out. GraphQL always returns HTTP 200, even for errors. Errors are in the response body. This confuses monitoring tools that look at HTTP status codes.

My view in 2016 was that GraphQL was genuinely better for client-server interaction patterns involving complex, nested data and varied clients with different data needs. It was not a universal replacement for REST. The extra complexity was not worth it for simple CRUD APIs. The decision should be driven by whether you actually have the problems GraphQL solves, not by what is fashionable.

Found this useful?

Share it with someone who'd enjoy it.