GraphQL is a product-developer-friendly and efficient method for fetching structured data from a server, designed to be an alternative to REST. It was developed in 2012 at Facebook, has powered the main iOS and Android apps for over four years, and is now used by dozens of Facebook apps on both native and web. Since it was publicly announced and open sourced last year, there has been a lot of activity around implementations and tools for different environments and languages. Companies like Pinterest, Intuit, Coursera and Shopify have already adopted GraphQL in their own apps, and a few weeks ago GitHub announced their new public GraphQL API. I believe this is just the start, and we’ll see a large uptake of GraphQL over the next year.
I’ll be speaking at ReactiveConf later this month about one of the major ideas underlying the many benefits of GraphQL: the use of a type system to expose the capabilities of a server and improve the client developer experience.
RESTful APIs are an uneasy compromise
With REST, there is a continuous tension between efficiently satisfying the data needs of specific clients, and keeping the number of endpoints manageable. The reason for this tension is that a server defines what data an endpoint returns, and the client merely requests it. Especially in mobile apps, the overhead of performing separate requests or of requesting extraneous data is often unacceptable, so we’re forced to add ad-hoc endpoints with custom response structures.
This means client and server are closely coupled, because changing client data needs require corresponding changes on the server. At the same time, REST doesn’t give us a formal way to coordinate these changes. A major pain point with REST is evolving an API efficiently while still supporting older clients. This often leads to endpoints returning data current clients no longer need, and has the danger of inadvertently disrupting older clients. It may also make client teams dependent on backend teams, slowing down product development.
Telling the server what you need
GraphQL is based on one of those ideas that make obvious sense once you hear about it: let clients specify their own data needs against the capabilities exposed by a server. Gone is the mess of relying on an ever expanding set of predefined REST endpoints to cover all bases, because GraphQL exposes one endpoint that returns the exact data you ask for in a single structured response. To make this work, GraphQL defines an application query language, a language that has been designed specifically for use by product developers.
Instead of coordinating requests and stitching together responses from different endpoints, clients now write queries that describe the exact shape of the resulting data they need, and the server builds up a structured response by evaluating the query.
How types enable coordination
What underlies this process is that servers define a schema, a type system that precisely describes what data is available to clients. And clients specify the exact structure they want a response to have in terms of this type system.
The type system thus acts as a formal coordination mechanism between different systems and teams. This also makes it possible to use validation and other powerful tooling to ensure at build-time that requests can be satisfied by the server at run time. The type system can guarantee that the data we access from our code is actually fetched as part of the query we execute.
As an example of this kind of tooling, I’m currently working on a native iOS client that uses code generation to generate query-specific model types. In effect, this means you can now rely on the Swift type checker to make sure errors in data access show up at compile time. Similar type checks can be performed using Flow or TypeScript for web clients or React Native apps, and I hope to show some early examples of this as well during my talk at ReactiveConf.
Supporting evolving data needs
GraphQL supports continuous evolution of clients over time in a very natural way. If the schema already contains the data you need, no change to the server is required at all. And if you do need to add a field to the schema, this won’t affect existing clients. In fact, at Facebook they’ve been very careful not to introduce backwards incompatible changes to the schema. Amazingly, Facebook’s GraphQL endpoint still supports 4-year old shipped versions of their iOS and Android apps! There are now over 1000 active versions connecting to the same endpoint, without any major issues.
Again, the use of a type system is immensely useful here, because it allows you to check at build time that changes to a schema are backwards compatible and won’t break older clients. This is something Facebook does as part of their build process.
We’d like to hear from you!
I’m excited to be working with GraphQL, and I believe its architecture holds great promise to help improve the developer experience of data-driven apps. Please join me at ReactiveConf or get in touch if you have experiences to share or would like to contribute to the tools we’re working on as part of Apollo.
Note: There are still some tickets left for ReactiveConf. Use coupon
devto for a 20% discount off the face value. This coupon is only valid for a few more days.