21 May 2020 by Patryk Zawadzki

What is GraphQL?

In this article, we discuss what all the fuss about GraphQL is and how the technology can transform the way your company builds web applications.

I could simply tell you it was a computer language designed by Facebook, and I wouldn't be lying, but you could find out just as much by reading its Wikipedia entry. To understand the importance of GraphQL it's crucial to look at it in the right context.

Templates

As the applications we rely on become more and more complex, the desire to separate how they work from how they look grows stronger. Years ago, and I mean years ago (in the 1990s), it was common for each platform to take care of its backend and also render all of its user-visible interface. This was the simplest solution, although customization quickly became a challenge. Modifying the appearance directly in the code meant that the application could no longer be easily upgraded, so various templating solutions were devised.

Some systems opted for templates to be written in the same programming language that the surrounding platform used. This is how Wordpress-based systems work to this day, with the template being the main logic loop. It mixes the code responsible for drawing the user interface (HTML) with logic that fetches data from the database and executes all the required plugins.

Others chose to utilize domain-specific languages (special languages created to solve a particular problem) to describe the looks, the platform would then interpret them when rendering a response. Chances are this is how your Magento-based store is styled today.

The first approach has the downside that programmers who modify the template need to be full-stack developers, with a strong grasp of both the backend logic (including its language of choice) and the languages used to build the interface (eg. HTML, CSS, JavaScript). As the template itself acts as the main logic loop it inadvertently affects business logic, while modifying the looks becomes a risk that you need to specifically test against. The page might look as it should, but what if the programmer forgot to include the call to your tax service?

The latter approach means that your frontend engineers would likely need to learn a new language and that a large chunk of their knowledge is going to be specific to the platform itself. While breaking business logic becomes much more difficult, at some point your organization is starting to hire Magento theme developers instead of frontend engineers. A potential candidate's vast knowledge of modern frontend frameworks is going to be irrelevant unless they learn how to create a theme for the platform.

Intermission: Servers and APIs

For two pieces of software to be able to talk to each other, they need to know how to exchange information, and how to interpret any data the other party might choose to send their way. There are standards that describe particular use cases, languages, and protocols that dictate how programs talk to each other.

Usually, the party with an established address is called the server and the party that connects to it is referred to as the client. For communication to begin, the client has to reach out (connect) to the server. Think of it like a hungry patron entering a restaurant; there's simply no way for a server to know the whereabouts of all the hungry people in town.

A communication standard meant for programmatic consumption is called an application programming interface (an API) and an address of a server implementing said standard is called an API endpoint. When a web browser connects to a web server, it's using its HTTP (the Hypertext Transfer Protocol that powers the web) API by connecting to its HTTP endpoint located at the address you provided in the address bar.

AJAX

Both mentioned templating solutions have their individual limitations beyond the ones listed above, yet the most glaring shortcoming is that they were developed in times where everything was rendered by the server. If every action of the user is taking a round-trip to the server, there's no way to support offline mode. If every interaction requires the entire page to be redrawn, how do we implement a live search of a catalogue of five million products?

That's how we arrived at hybrid solutions where most of the layout would be rendered by the server, but another—asynchronous—method allows the user interface to fetch additional data as needed. That's where AJAX (asynchronous JavaScript and XML) first appeared. While AJAX was more of a concept than a standard, it proposed a way to fetch snippets of HTML (or XML if you insisted on staying true to its name) then add them to the page that was already rendered.

AJAX made new kinds of website elements possible to implement, but since there was no standardized way to do it, developers from different companies (and sometimes from different rooms in the same office) had very different opinions on how everything should work. Eventually, server-to-server communication was largely standardized around a specification named Simple Object Access Protocol (SOAP), while browser-to-server communication chose Representational State Transfer (REST).

Intermission: Resources and Procedures

SOAP and REST each use a very different approach to interface design.

SOAP is a Remote Procedure Call (RPC) mechanism. It offers a list of predefined operations; the "procedures", with each procedure accepting a predefined number of parameters, and returning a number of named values of predefined types. A hypothetical addition procedure might accept two parameters, a and b, of type number and return a single value named sum, also of type number.

REST is an API revolving around resources. Each resource represents either a single entity or a collection of entities of a particular kind. Every resource supports a number of operations that can be: created, read, updated, and deleted. A hypothetical books resource collection might contain a single resource representing The Little Prince by Antoine de Saint-Exupéry. We could then update it with the year of publication, an International Standard Book Number, and later ask for the resource to have the information sent back to us.

Single-Page Applications

Building dynamic interfaces with AJAX was a pain. This was because the code to draw the same parts of the user interface had to live both on the server- and client-side; the first version would be generated by the server and sent to the browser. Then, as the user interacted with the page, certain parts would need to be redrawn by the JavaScript code running in the browser. Whenever visual changes were made, they would have to be made in both places, potentially requiring different types of talent for each part. This is hardly an ideal solution. Recent years gave rise to a new type of frontend frameworks, ones where the entire application is rendered by JavaScript in the browser. The server no longer needs to prepare the initial version of the page as the so-called single-page applications (SPA, named after the fact that the entire navigation happens without leaving the application) only use the server to fetch the necessary facts about objects, not the page layout.

Applications written in React, Vue.js or Angular have no use of whichever outdated template solution was implemented by the server. The architecture of headless servers (as the servers no longer have a user interface) with rich clients allows frontend engineers to build the entire user experience using technologies they're familiar with, and in languages of their choice. Updating the text on your about page no longer requires a backend developer, but as everything becomes API-driven, the architecture choices behind the API become the limiting factor of the team's performance.

SOAP did a lot of things right, but in doing so, it mandated a very complex representation for any information transferred, which in turn made it difficult to work with for JavaScript programmers. REST's insistence on dealing with object states instead of state transitions means there is no obvious way to represent abstract concepts that don't directly map to tangible objects.

To understand the limitations of REST, imagine an API representing the apples I hold. Every time one of my friends uses the application to claim one of my apples, I want to decrease the number of apples available.

A naive solution would be to introduce a ‘me’ resource with a field holding the current number of apples at hand. However, since reading and writing are distinct operations, there is no safe way of decreasing the number by one without risking what's called a race condition: the case where two clients read a value and then both try to subsequently modify it, each oblivious to the other’s actions. Assuming there are 5 apples to start with, both clients would read the number 5 and then issue an update, both setting the number to 4.

In reality, you need to work around this by either introducing an explicit resource for each apple or a resource for each act of taking an apple, even though the latter is an abstract concept that does not represent a tangible object. If you tried to implement the hypothetical addition procedure example given earlier, you'd face similar issues. Real-world application logic is full of atomic operations and state transitions where the client simply can't be trusted with determining the resulting state, either because of possible race conditions, or because of business or even legal constraints, and this is where—unfortunately—the create/read/update/delete mantra of REST falls flat.

There is another limitation common to both REST and SOAP. We've celebrated the fact that single-page applications mean no longer having to update the server each time the client is modified. However, as the exact set of fields returned by the server is controlled by the server itself, when we need to display additional data we face a choice to make: either modify the server to send more fields or issue an additional request to the server. A server returning more fields could mean that in the most common cases we're sending over data that is not immediately useful to the client and we're wasting network bandwidth. This is called over-fetching. Forcing the client to make an additional connection to the server in the few cases when more data is required means a longer waiting time for the end-user as each connection is a cost we pay in network latency (the time required for data to reach the server and return). This is called under-fetching.

GraphQL

Finally, we are ready to understand what GraphQL really is. In short, it’s a computer language designed specifically to solve the problems of a modern web developer. It is also a collection of API specifications that describe how to speak GraphQL over HTTP, the protocol that web applications use.

While GraphQL is often compared to REST, in reality, it's much closer to SOAP. It's an RPC mechanism that offers a collection of named operations (SOAP calls them procedures, whereas GraphQL has queries, mutations, and subscriptions).

Unlike SOAP, it uses a simple data format to represent objects. For this reason, it's very simple to deal with in JavaScript code.

Unlike REST, it revolves around named operations instead of resources. That makes it easy to implement scenarios that don't map to tangible objects or that operate on multiple objects at the same time.

Unlike both SOAP and REST, it requires the client to specify the set of fields (including related objects) it expects in return. This deals with the problem of under- and over-fetching while maintaining forward compatibility.

Unlike REST, GraphQL comes with an introspection interface which means API endpoints are self-documenting. This was an issue SOAP eventually solved by distributing Web Services Description Language (WSDL) files, while REST awkwardly tries to solve the same issue by generating documentation pages that are often neither useful for human reading nor suitable for computers. The introspection mechanism interface gave life to a rich tooling ecosystem including automated ways to detect whether the client's code refers to any API areas the server considers to be deprecated (prior to their actual removal).

Given that GraphQL separates its protocol specification from its transport specifications, it's possible for an application to use the same GraphQL engine for both resolving queries sent by web clients and for executing queries internally within the application, thus becoming the single data-access mechanism for all business logic.

Given all of its technological advancements and the standard now being governed by its own GraphQL Foundation, operating under the Linux Foundation, don't allow anyone cajoles you into thinking that GraphQL is nothing more than a passing fad, or just some hyperbole peddled by Facebook engineers who don’t understand REST.


Make sure to follow us on Twitter to stay up to date, and feel free to ask us any questions on Spectrum!

— Share