GraphQL: Designing APIs for the Internet of Everything

GraphQL is not just changing the way we think about APIs, but transforming how we build applications for the modern internet.

GraphQL was conceived when Facebook was rebuilding their mobile experiences in 2012 and later released to the public in 2015. GraphQL technology offers many features that make it greatly useful and helped it gain popularity. At its core, GraphQL questioned how we think about data and build APIs.

We explore GraphQL, the data query language, and go through a concrete example of designing and building new APIs. We explore the benefits of GraphQL and contrast it with other approaches. To understand why GraphQL is significant we need to think about how we build customer-facing experiences today.

Designing APIs for the Internet of Everything

Imagine that you are part of the new hot tech company, ‘Bookl.y’, the Netflix of Books. Bookl.y launched a great website and now you are tasked with extending the Bookl.y experience to smart TVs, phones, tablets, and smart glasses. Bookl.y is also considering new experimental mediums like voice and possibly launching their own hardware products.

Let’s start by looking at the challenges we will face building all these different experiences. We will specifically focus on data APIs.

Design Considerations for Modern Devices

You are giving wireframes for each device and you are asked to implement them. But you know designing websites is not like designing for other devices.

When you think about designing for mobile, you have to consider the small screen size, touch control gestures, slower internet speeds in contrast to desktops (and much slower internet speeds in less developed areas). Users might have set data limits for the download content, which will affect how you load images, audio, and video.

When you are designing for TVs, you have to consider the huge amount of screen real-estate, while also accounting for people sitting away from the screen. A TV is controlled using simple direction-based remote-controls (up, down, left, right, ok, cancel), and usually has access to a more reliable internet using wi-fi or wired connections than phones.

Tablets sit in the middle between mobile and TVs. Some tablets have smaller screen sizes, some are bigger. Some tablets run native apps (iOS devices) and some rely heavily on web-based apps (Chromebooks).

Then there are smart glasses or VR headsets. How do you design for those? The user’s view is totally immersed in your experience. The real estate is significantly different, the user’s viewpoint is small but the user can expand it by moving their head. You must be able to control everything using a few buttons (ideally just one).

When you consider voice or new hardware like headphones or new iPods, you have completely new considerations. Sometimes there are no screens at all and you must provide content via voice.

The complexity of designing APIs for all these cases is overwhelming. Even if you are able to roll-out a V1 API for all these devices, consider future changes. Changes in the future will require changes in many places for many devices. Managing different APIs for different devices/interfaces is a complex business.

Mapping Front-End Content to Data

Take a look at the wireframe for the main browse page for Bookl.y below. We have a featured book that takes over a big portion of the screen real estate while the rest of the page has a large number of books. Books have star-ratings. They might also have customer reviews displayed.

Now think about how data is fetched for this page. There is some HTML, JavaScript, and CSS that is needed to render the layout, as well as a bunch of images. For specific books, we also need the book titles as well as link URLs to book contents and star ratings. Additionally, the featured books require some customer review of the book. We might want to feature several books and we need to fetch that data for each.

Let’s consider how we might load data into this page. We have the website static content (the HTML, CSS, and JavaScript) and book data which is dynamic content (we want to feature different books at different times to different users and might want to customize or personalize the content). The page itself would probably look the same for almost everyone viewing it thus it’s static.

1. Fetch all resources server side

When you request www.Bookl.y/browse, the backend server can return HTML with content already filled-in (we will pull all book titles, along with their ratings, reviews, and image URLs).

This approach causes the page load to be very slow. Instead of loading the static content in a few milliseconds, we are dynamically doing the work and we can’t return the page until we fetch all the data we need, which could be from multiple data authorities (think multiple back-end servers). This could be a good thing or a bad thing. For static content that will never change this is good. For a page like Bookl.y this is bad not just because it’s slow, but it makes the page less dynamic. We have to request the page again if we scroll through books, or we have to get a list of the entire book collection before returning content to the browser which will be terribly slow.

Additionally, any work you do for your website doesn’t translate to any work you do for other mediums. Your backend and frontend are tightly coupled. Modern software applications don’t follow this approach. I do not recommend doing this.

2. The Old Fashioned RESTful API

You fetch the static website content separately from the dynamic content. The static content pulls the dynamic content from backend servers using RESTful APIs. You will need to build different APIs to get different parts of the content. For example,

Get a list of features books
GET /books?featured=true

Get a list of books to browse, which should be scrollable
GET /books?page=1

For each book, fetch data for the book (including image URLs, ratings, and possibly reviews)
GET /books/{bookid}/

Optionally the reviews and could be exposed as separate resources
GET /books/{bookid}/reviews
GET /books/{bookid}/ratings

The above approach is commonly used in many applications today because the frontend and backend are decoupled. You can introduce new recommendation algorithms, change everything in the backend, and the UI doesn’t have to change.

If you build new apps for phones, tablets, or TVs, your front-end code can pick and choose what backend resources it needs and request them only if necessary. This also allows resources to be requested in small increments and loaded as they become available. This speeds up page load time. You are able to serve static content for your website separately from dynamic content and therefore you can put your static content on a CDN, saving money and improving customer load time and therefore customer experience. Because resources are granular, I can fetch the data I need and the data I need only. This allows us to reuse the APIs when building any platform/user interface we want.

The disadvantage here is you have to make a ton of requests to pull all the data you need. This makes the application slow because you have to wait for many network requests to come back. You can read more about designing restful APIs here.

3. Build a mega API, GetBrowseContent

In order to reduce the network latency, we can simply merge responses. In order to reduce the number of requests to fetch data, you can create mega APIs.

Group multiple resources into more coarse-grained resources (list of books vs book vs book author). This reduces page load time and network calls. The calls themselves might be slower since they are fetching more data (so more latency on backend server side).

GET /BrowseContent/

Get /RecommendedBooks?filters=bestbooks

GET /Featuredbooks/

GET /ScrollableBooks?genre=history

The disadvantage here is that the data is tightly coupled to the front-end. We are providing data that the website needs (to the maximum amount possible). If the UI changes, we have to change the API. This is also extremely hard to make generic and extend to TVs, tablets, and mobile.

4. GraphQL

And of course, you can use GraphQL. To understand why we would use GraphQL and how it can help us, let’s try looking at the design for different devices and user interfaces.

Expanding the Customer User Interface

Mobile Apps

The mobile app is very similar to the website, but the data is laid out differently, and the amount of data is different (number of books). There is also no customer review for featured books but we do show customer reviews for browsable books. How can we leverage the APIs we built for the website for the mobile app?

Virtual Reality

Virtual reality provides a really exotic and interesting interface. You have the main view field (purple in color) and then you can see through the entire interface. You only have one button to click. Things are sized differently because everything is right in front of your eyes. There are no featured books, just a huge library of things to browse.

Voice

Voice is a new frontier for computer-human interactions. With voice, there are no visuals at all. Just recorded voice. When you use Bookl.y via voice, you are expecting to have Bookl.y read that book to you.

 

Thinking about the Internet of Everything

When we consider the designs we have for different user interfaces on different mediums, we need to reconsider how we design our APIs because they impact the quality of the customer experience.

  • For a wireless device, resource utilization is important. Specifically requesting a lot of data greatly reduces battery life, and customers do notice. Additionally, for devices that depend on the wireless mobile internet like 2G, 3G, and 4G LTE, internet connection could be great or bad and it directly affects page load time. Requesting fewer resources in larger batches reduces battery drain and response time.
  • Visual real estate can vary greatly between devices. The most compelling user interfaces will be specifically designed for how people interact with that interface (iPad mini design will be different than iPad pro, etc.).

From a software engineering and developer productivity perspective, you’ll want to solve all the issues we faced here by creating APIs that are flexible so they are closed to modification but open to extension. You want your collection of resource APIs to allow any new device/user interface to be on-boarded with minimal effort. At the same time, when building the backend API you don’t want to optimize every use-case/every device. You want the front-end developers to have full control of how they build their interfaces and allow them to iterate quickly and freely.

Introducing GraphQL: a flexible query-language for your API

Now consider if there was something you can do to solve all your problems. The solution to every software problem is a new layer of abstraction. In this case, Facebook presented us with GraphQL.

GraphQL is fundamentally just a query language (think SQL) but it can be served through HTTP/s through APIs. GraphQL allows us to think about APIs with fine-grained control over requested resources. It is designed for the internet of everything.

We explore what GraphQL is through concrete examples.

1. Describe your data

Simply GraphQL provides a way to describe all the data you have and the data you request.

For Bookl.y we define basic types

type Book {
title: String
author: Author
published: Date
small-image-url: String
medium-image-url: String
large-image-url: String
star-reviews: [StarReviews]
customer-reviews: [CustomerReviews]
voice-url: String
book-url: String
}

type Image {
size: String
url: String
}

type StarReviews {
rating: String
count: Int
}

type CustomerReviews {
customerid: String
customername: String
reviewText: String
datePosted: Date
}

type Author{....}

type Date{....}

...etc

We also define types of books we want to discover. This is where we map business logic to datatypes we have. FeaturedBooks will come from FeaturedBookService and BrowsableBooks will come from BrowsingService

type FeaturedBooks {
booksList: [Book]
}

type BrowsableBooks {
booksList: [Book]
}

GraphQL allows for introspection so this data can be discoverable. You can query to find out what data is available and what types (GraphQL provides strong typing).

2. Ask for what you want & 3. Get predictable results

To get data, ask for what you want precisely and get precisely what you asked for. No more guessing what data you need, and no more getting data you don’t care about.

Web App Example

To get data for this website we would have the following query and corresponding results.

 Web App Query

{
featuredBooks(first:2) {
booksList {
books {
title
author
large-image-url
star-reviews
customer-reviews
}
}
}
BrowsableBooks {
# GraphQL queries supports comments
# 'Y3Vyc29yMQ==' is pagination token

booksList(first:20 after:"Y3Vyc29yMQ==" {
books {
title
author
small-image-url
star-reviews
}
}
}
}

Web App Results

{
"featuredBooks" :{
"booksList": [
{
"title" : "The C Programming Language"
"author": "Brian Kernighan and Dennis Ritchie"
"large-image-url" : "www.cdn.com/cp1.jpg"
"star-reviews" : "4.5"
"customer-reviews" : "#define BEST_BOOK_EVER(THIS)"
}
]
}
"BrowsableBooks" : {
"booksList": [
{
"title" : "The Go Programming Language"
"author" : "Alan A. A. Donovan and Brian W. Kernighan"
"small-image-url" : "www.cdn.com/gop1-small.jpg"
"star-reviews" : "4.4"
"customer-reviews" : "reading this is part of my daily goroutine now"
},
{
"title" : "The Rust Programming Language"
"small-image-url" : "www.cdn.com/rp2-small.jpg"
"star-reviews" : "4.3"
"customer-reviews" : "everyone should immutably borrow this book from friend"
}
]
}
}

Virtual Reality Example

Virtual Reality Query

{
BrowsableBooks {
booksList(first:15 after:"Y3Vyc29yMQ==" {
books {
title
author
small-image-url
star-reviews
customer-reviews
}
}
}
}

Virtual Reality Results

{
"BrowsableBooks" : {
"booksList": [
{
"title" : "The Go Programming Language"
"author" : "Alan A. A. Donovan and Brian W. Kernigh"
"small-image-url" : "www.cdn.com/gop1-small.jpg"
"star-reviews" : "4.4"
"customer-reviews" : "reading this is part of my daily goroutine now"
},
{
"title" : "The Rust Programming Language"
"small-image-url" : "www.cdn.com/rp2-small.jpg"
"star-reviews" : "4.3"
"customer-reviews" : "everyone should immutably borrow this book from friend"
}
]
}
}

 

Notice how flexible GraphQL as the language for describing and querying our data. We can get any data we want and extend our GraphQL API to any device/user interface.

How GraphQL Unlocks Flexible APIs for Everything

Wow That’s Awesome. I know, right! Bookl.y needed to expand to multiple devices and multiple interfaces. We wanted to develop applications for several mediums and several kinds of front-ends. GraphQL allows us to have one API and have it be flexible enough for any use case.

If our smart TVs wanted to support audiobooks, (and our backends already support audiobooks), we just need a new query parameter to retrieve audio-book-url.

GraphQL solves the problems of data flexibility and extensibility. It has a strong schema (personally I am a fan of the safety of strong typing and schemas).

It also solves the problem of reducing energy consumption and lowering battery drain. By only getting the data you need, the data transported is smaller. You are able to paginate and optimize your query to get any data you want. GraphQL reduces network load by reducing of data transfer, thus making your applications faster.

GraphQL hides the complexity of the backend, which is doing the aggregating of data from different sources, filtering, and joining. It’s a truly powerful tool and really helps accelerate frontend development in all forms (web, mobile, VR, and voice).

Deploying GraphQL and Getting the Data

My goal was to motivate how GraphQL could be useful for your application and how it changes how you think about data. But there is more than just designing the API. There is work to actually deploy a GraphQL server to handle queries and connect to your backend data sources.

GraphQL doesn’t dictate how the data is retrieved. You can use HTTP/s and many libraries out there support that. GraphQL doesn’t dictate the server software either. GraphQL defines the language that describes the data schema and allows you to have flexible queries. It supports schema validation, pagination, filtering, compression over HTTP, introspection into code, and support for multiple languages.

If you are interested in learning more about GraphQL, check out the official page.  You can use GraphiQL to play around with GraphQL. I am considering writing an article on deploying applications with GraphQL and examples of how to manage the backend/server side of things. If you are interested send me an email at abdallah@softwareengineeringdaily.com.

Also, check out the various Software Engineering Daily episodes that cover GraphQL:

What about security?

GraphQL leaves authentication and authorization to be part of the business logic layer. This way, GraphQL is extensible and allows you to integrate with how you do authentication and authorization in your system.

Could we have solved the problems you mentioned some other way?

We can of course. There are always multiple solutions to a problem with trade-offs. GraphQL was introduced to be reusable and general purpose. The Netflix Serverless-like Platform with Vasanth Asokan discusses how Netflix solved the problems of optimizing their queries by allowing frontend developers to write their own query plugins. Check out the episode. Knowing about GraphQL, Netflix might have solved the problems differently today.

Should I use GraphQL for my frontend now?

Not necessarily. GraphQL is not a one-size-fits-all solution. It is very powerful when used to deploy front-facing APIs for several interfaces and applications. GraphQL is allowing a growing number of people to really expand their platforms into different mediums. I can’t wait to see what cool virtual reality and voice experiences open up because of GraphQL.

 


The views presented in this article are Abdallah’s and don’t represent the views of his employer or Software Engineering Daily.

Abdallah Abu-Ghazaleh

Toronto

A software developer who is passionate about building things, Abdallah is interested in tackling the problems of scale for software, people, and ideas. Abdallah has experience working on embedded and distributed systems. Abdallah enjoys talking about technology, software development, tech ethics, and human development.