I’m a chronic networker. When there isn’t a pandemic, you can find me talking to people at restaurants, bars, and meetups on a near-nightly basis. I can’t help it, I love learning about other people and seeing how we can help each other through this crazy ride we call life. As an engineer, I naturally mingle with other technologists as they form the basis of my existing network. More often than not, during my first Old Fashioned of the night, the topic of “latest technical trends” comes up during our conversation. We are all feeling the same pain right now, as old patterns such as REST do not adequately address the performance and organization problems of consuming a complex web of data. Without fail, the conversation touches on GraphQL at least once.
I’m unapologetically passionate about GraphQL. That said, I am no fan boy. Every technology has it’s tradeoffs, and GraphQL isn’t the right fit for all projects! My foray into GraphQL began during my tenure in the San Francisco Bay Area, while building Jobstart with my good friend Zach Tratar. During that time, I got involved in the Apollo community and, from there, things have just continued to accelerate. GraphQL has moved from an esoteric new technology into a mature mainstream solution, not only for consumer applications but also enterprise-grade solutions.
Every engineer has a mental model for how software ought to be built. It is part of how our minds work, always searching for ways to organize the chaotic lake of information around us into nicely groomed streams that fit together seamlessly. When discussing GraphQL with engineers who have not used it in their projects, an inevitable question arises: What is GraphQL? Behind this question is a broader question: how does GraphQL fit into my existing mental model of how software should be architected? I’ll try to address this question at a high level now, in the hopes that it’s helpful to other engineers and technical leaders as they consider adopting GraphQL in their organizations.
Let’s take a second and talk about what problem is actually driving the adoption of GraphQL: rich experiences require lots of interconnected data. If you are using a RESTful API, you no doubt feel the pain of this problem. All sorts of hacks on top of REST have been constructed to solve for this, such as
expands URI parameters that cause your RESTful API to return nested relational data. But they inevitably don’t scale, as your product’s API drifts further and further away from your actual product requirements and your UI layer is forced to make more and more API calls in order to satisfy the data requirements of it’s latest user experiences. Not only does this provide a sluggish user experience, but it also overloads the API’s production database in many cases with a “carpet bombing” of N+1 requests. I’ve seen and experienced this time and time again at companies that use RESTful APIs and segment their engineers into “frontend” and “backend” functional roles. It may not be inevitable, but it is probable.
A Working Solution
GraphQL attempts to solve this problem at the API protocol level, by allowing backend developers to leverage an “expandable” RPC protocol designed by Facebook for building rich interconnected user experiences. Backend developers define a “schema” for the API in the same way that they define database tables. Every piece of data has a defined “type”, with explicitly defined relationships to other data types. Rather than writing a “controller”, like they would with a RESTful API, backend developers write “resolver” functions for each data type that do roughly the same thing as a REST API controller such as querying the database. When the client needs to render a view, it sends a “query” to the backend. The backend parses this query and invokes all necessary resolver functions in order to fetch and join the various data types together. It then sends back all of the necessary data to the client, turning N+1 requests into a single round-trip. As an added benefit, because the data is all aggregated within a single request context, the number of database operations can usually be cut down to 1 per traversal-type pair rather than N+1 as it would be with REST. Real time data is also supported out of the box via GraphQL Subscriptions, so the server can push data to the client on the same protocol without building any sort of custom real-time API.
A key difference between GraphQL and REST is that the backend engineer no longer has to think about specific user experiences in order to provide fast interactions for the client side application. Instead, the backend engineer can think about the necessary operations that need to be performed against their pool of data and write pseudo-RPC methods (Queries, Mutations, and Subscriptions) to handle these operations. Because the client can expand out from the initial returned data type (such as a User object) to related data types (such as Posts made by said User) without the backend engineer writing custom “expansion” code, the coordination burden between backend and frontend engineers increases logarithmically to the complexity of the product over time. This is in stark contrast to a linear or exponential increase in the coordination burden over time for RESTful APIs and even other next-gen protocols like Google’s gRPC. From a technical strategy standpoint, this is huge.
We’ll be writing more content about GraphQL over the coming weeks, showing you exactly how to adopt and leverage GraphQL at any scale. We’ll also be hosting GraphQL Texas, the first ever GraphQL meetup and yearly conference in the largest state in the lower 48. Check out our meetup page here.