The term GraphQL is getting a lot of attention lately. As its name suggests, it’s a query language, just like SQL (Structured Query Language). Unlike SQL however, it’s used not in database interactions, but in web APIs. To explain the benefits it can bring there, we’ll explore GraphQL in a series of 3 blog posts, of which this one is the first:
- Context: in the blog post we’ll put GraphQL in its historical perspective and wider context, and will discuss its general pros and cons
- Syntax: this blog post will offer an introduction and general overview of the GraphQL syntax and how it’s used to collect data by the consumers of your API
- With Java and Spring: we’ll discuss 2 prominent Java libraries that enable you to create a GraphQL server API. The first relies on plain Java while the second build on the Spring framework
Early web API history
Software applications often have a need to talk to each other, whether it be banking applications that need to collaborate for financial transactions or a single-page web app that needs to retrieve information from its backend server application. Ideally, this is done with a degree of reliability and in a way that’s easy for software developers to implement and maintain.
First defined in 1998 (and published in 2000), Simple Object Access Protocol (SOAP) was a big step forward in that regard, because it provided a uniform way for two applications to communicate, with a clear contract on the format of the data and with increasingly widespread support by programming libraries. Because SOAP is based on official web standards that are maintained by the World Wide Web Consortium (W3C), and inherently involves security functionality, it is a reliable choice for API development. Even so, it involves a lot of protocol and programming ceremony, complicated data structures, not to mention a lot of XML.
REST (short for representational state transfer) originated in Roy Fielding’s PhD dissertation in 2000. Unlike SOAP, it’s an architectural style rather than a protocol. Despite that difference, in practice it offers a viable and more developer-friendly alternative to SOAP, by relying on meaningful and consistent URLs (e.g. /doctors/5/appointments), HTTP verbs (GET, POST, etc), statelessness, and (in practice at least) JSON as the typical structure of the data. By 2010 the popularity of REST had overtaken SOAP (which nevertheless still serves as the backbone for many systems – particularly in finance).
Problems with REST
Because REST emphasizes having separate endpoints for each of your resources (e.g. patients, doctors, appointments, schedules, etc), the number of endpoints can become quite large. That adds a lot of flexibility, but can also mean that your frontend needs to send large amount of requests to fetch all the data for a single page of your webapp.
On top of that, a REST API response for a given endpoint generally has a fixed format and fixed degree of detail, regardless of what information the user of the API does and does not need. As a result, data transfer in a REST API can be suboptimal (or require additional developer effort to make the response format more flexible, e.g. via query parameters).
At least in part due to these issues with REST APIs, in 2012 Facebook started working on an alternative approach, called GraphQL. That work remained internal until it was publicly released in 2015 and finally moved to a separate foundation in 2018, where the GraphQL specification is managed.
In brief, GraphQL is a specification that details how to use a single HTTP call to retrieve data that is tailored to meet the API consumer’s exact needs. The basic trick is to send a POST request with a request body contains all the information that the server needs to return all the data the consumer needs and only the data that the consumer needs.
Because it is (based on) a specification, GraphQL provides predictability and reliability more similar to SOAP, while its JSON-esque syntax and lack of complex ceremony allows for more developer convenience. Furthermore, because a GraphQL API consist of a single endpoint and allows the developer to exactly specify what data should and should not be returned, it also avoids much of the issues with REST.
As is evident from its name, it’s is a query language. And like SQL, it builds on a schema, has the equivalent of tables and where-clauses and allows you to declaratively specify exactly what information you want to retrieve. It also has the distinction between queries which return information (like SQL select statement) and mutations which modify data (somewhat like SQL update statements, but potentially more powerful).
Although GraphQL offers a useful alternative to e.g. REST, this does not mean that it can entirely replace REST, that it’s always the optimal choice or that it does not have its own constraints and caveats.
The first thing to note is that GraphQL adds quite some complexity. In larger web APIs that serves many different consumers, that complexity has a high return-on-investment, but in smaller APIs it may be more prudent to stick with REST. Similarly, when the API provider and API consumer are tightly coupled (e.g. for a small internal application), you may not need the flexibility that GraphQL offers.
Another issue stems from the fact that GraphQL always makes use of the HTTP POST verb, regardless of whether you’re making requesting data or performing update, because you need to pass your query via the request body. As a result, the well-established HTTP caching features are not in play when using GraphQL (although workarounds do exist).
Furthermore, despite being statically typed, GraphQL still lacks (stringent) conventions with regard to how errors are returned (besides using an error field). This means that you still need to provide API documentation and/or that the API consumer is required to parse and loosely interpret the error content. Contrast this to REST, which builds on the HTTP spec and its well-defined and widely used range of status codes.
Similarly (and again contrary to REST), the specification does not offer a way to deal with other content types (i.e. mimetypes; for example when uploading or downloading files), because GraphQL depends on JSON-like queries and JSON responses.
Despite these constraints, the real take-home message here is to use a tool based on the job at hand. In some usecases that may not include GraphQL, but in others it will definitely shine.
It should be clear that GraphQL has a lot of promise, learning from and building on the best parts of its predecessors. In the next part of this series, we’ll go into the syntax of GraphQL, to be used by a frontend application or any other API consumer that requires tailormade complex data.
Alain Van Hout
Java Software Crafter
Alain Van Hout (36) is a Java Software Crafter with a Master in Science (Biology) and experience in academic research concerning evolutionary biology. Currently, Alain is working on web applications and API integrations at the genomics data analysis provider BlueBee (Mechelen), where he combines his background in biology with his passion for software Craftsmanship.