Recently there has been a lot of talk about Facebook’s GraphQL specification, and exactly how it transforms the way applications are now able to interact with each other. In fact, its virtues have become the subject of debate with Kin Lane, publisher of APIEvangelist.com saying GraphQL Seems Like We Do Not Want To Do The Hard Work Of API Design and Apollo’s Sashko Stubailo offering a rebuttal claiming that GraphQL is actually the next generation of API design. Meanwhile, Github has given a major endorsement to the spec, recently indicating that GraphQL will play a major role in the future of its platform.
To be clear, GitHub is not actually replacing their existing REST or Push (Webhooks) APIs, as confirmed by ProgrammableWeb editor-in-chief David Berlind. But with Facebook and GitHub now pushing GraphQL, is the tide unjustifiably switching away from REST? Should you follow?
Query languages, of which GraphQL is one, are not a new technology, or even a new idea. Instead, as both Facebook and GitHub point out, it is a solution to a problem they are currently experiencing - a solution they came to by disregarding several key principles behind REST, key ideas that were implemented to solve other problems that were being experienced.
In the GraphQL vs REST debate, somehow this aspect seems to get lost completely. GraphQL and REST are designed to solve different challenges - different problems. GraphQL is designed specifically to allow the querying of data models, while REST is designed to act in a similar fashion to the semantic Web - allowing us to have agile, changing, and versionless APIs.
In many respects, that means when we are comparing GraphQL to REST, we are comparing apples to oranges. Just as when we compare MySQL to MongoDB - both have strengths and weaknesses (if you don’t believe me, just listen to the sales teams for each).
Where GraphQL Shines
Unlike REST, GraphQL is designed to access multiple resources simultaneously. This means that you are not only able to be more precise in not only retrieving just the data you desire (something that is built into some of today’s modern RESTful APIs), but you are able to do so across multiple resources/ data models (with data joins automatically built in) in a single HTTP (or other applicable protocol) call.
GraphQL is also designed to be incredibly structured (so much so that the order of properties in the response is critical). This means clients will know exactly what to expect (and in what types) without having to pull in JSON or XML schemas. It also means the API is much easier to document as the possibilities are limited to its models, not its representations and dynamically managed relationships.
Where REST Shines
REST isn’t designed to be model oriented, or a query language, but rather to be an abstraction or representation of the underlying data systems. However, while many of the differences between REST and GraphQL focus on solving the same problems, REST specifically is designed for the separate evolution of the client and server - with the concept that one can continue to evolve and change WITHOUT impacting the other (something that we have not quite mastered on the REST side).
REST is also designed to provide a uniform interface between the client and the server - meaning that the client and server should be able to communicate in the same manner or in the same format. Where-as a well built REST API should have the ability to support multiple content-types (XML, JSON, whatever the future may hold), GraphQL requires the use of the GraphQL format regardless of what content type the user is working with (note, GraphQL does support multiple content-types as well, although JSON is listed as the preferred format - a preference that REST avoids).
Another area where REST excels in its ability to provide error and response feedback, utilizing the HTTP Status Codes and descriptive error messages (Google Errors, vnd.error, JSON API Errors) when used over the Hypertext Transfer Protocol. This allows the server to inform the client of key components (created, updated, not modified, not found, gone, etc). Whereas searching for an item that was deleted in GraphQL does not in itself inform the user of any past actions or pending states, but rather returns no results.
But perhaps the most important benefit of REST, one that’s lost in GraphQL is HATEOAS. Hypermedia as the Engine of Application State was specifically designed to eliminate the rules engine from needing to exist on the client side - rather acting as a way to represent object state in a stateless environment.
It’s just as important to note that there is a huge difference between an API that utilizes hypermedia (ie we quickly implemented HAL, JSON API, JSON-LD, etc) and an API that is hypermedia driven (ie the links dictate the actions you can take, such as with StormPath’s API).
Arguably, most “REST” APIs fail to fully understand this context, and those that do create the very problem that GitHub is trying to solve with GraphQL - multiple HTTP requests to do one thing. However, by removing HATEOAS from the equation, again GraphQL has tightly coupled the client to the server, meaning the server’s rules cannot evolve without breaking the clients’.
So Which is Better?
Like the Java vs Node.js debate that occurred at API:World, the answer shouldn’t be based on personal preference, but rather on business needs. The same holds true with the GraphQL and REST debate. Neither one of these formats are perfect in their current form - and both are trying to solve very specific problems for their organizations.
In the case of Facebook, where they control both the client and server (ie their mobile API and their mobile application) the utilization of GraphQL makes perfect sense. Because their GraphQL API is not available to public developers, they can afford to change the server without impacting the mobile client too greatly - and if they do, they can work with their respective teams to find work-arounds/ fix any potential blockers.
GitHub likewise wanted an option to reduce HTTP calls (60% of requests to their database tier), and have an easier format to document their API from their code (a different issue altogether). To do this they drew many similarities between their REST API and their GraphQL API, and ultimately decided that the benefits of their REST implementation did not outweigh an GraphQL implementation in all circumstances
However, that does not mean that in GitHub’s case, pushing out a public GraphQL API was the right choice. In an effort to reduce calls, they are giving up the very layers of flexibility that I believe will drive future APIs. In essence, they chose a solution to one problem they were facing, but in doing so disregarded solutions for the problems REST was designed to solve - harkening back into a more SOAP like structure (not so much in the sense of classes and methods, but in the strict sense of being tightly coupled to the server’s architecture and underlying models).
Again, arguably you could say that REST runs into the same issues - and there is some truth to that, although more so due to our lack of understanding of proper implementation. Likewise, you could also treat SOAP as an interface, however it requires a lot more work on the server side to maintain the perceived abstraction.
Is there a Better Way?
Let me be clear in saying that again, you shouldn’t choose any format without first researching and evaluating your needs. With GitHub’s decision, I trust that there are multiple justifications within the business for the launching a GraphQL endpoint. Multiple reasons to forego the benefits of REST with an API that inevitably tightly couples any consumers and constrains their flexibility to freely change the API in the future.
As such, it’s important to note that while this may be the best interim decision for GitHub, it may not be the best way. And it may not be the way forward long-term (GraphQL could absolutely be the future, I’ve been wrong before - I just do not see it happening in it’s current form).
Instead, I think REST is already starting to transition towards solving its own problems. Hypermedia languages are moving more towards being action driven instead of resource driven - meaning they provide more information that allows the machine to present the information dynamically instead of requiring careful user implementation in each case. This can be seen with two newer specifications: Siren and CPHL.
At the same time, as HATEOAS becomes more used within RESTful APIs, more and more leaders are focusing on reducing the need for API calls. About two years ago, Owen Rubel proposed a concept of API Chaining, of which I’ve adapted as my own brainstorming document - a way to make one HTTP call across multiple resources - and retrieve just the data you need back - while also respecting the server’s rules and dynamically pulling in resources via the hypermedia links.
Early benchmarks tested against idea have not only been able to successfully handle multiple resource calls with a single HTTP request, but significantly reduce the processing time required. Using chaining when attempting three calls has shown a reduction of up to 66%, or a speed increase of between 0.2 and 0.8 seconds over making the three calls individually.
Then there is also the sixth constraint of REST, which very few people are talking about. Code on Demand - a way to for the client to be self-updating, self-evolving - allowing the server to break backwards compatibility without breaking backwards incompatibility.
Fielding has always envisioned a versionless API. An API that could evolve in a way similarly to the Web itself. GraphQL, while an incredible tool with many valuable use cases, takes us further away from that vision.
Learn more about RESTful API Design and Hypermedia in my book, Undisturbed REST: a Guide to Designing the Perfect API