 Hi, everyone. My name is Brooks. I am a platform engineer at GitHub, where the team that I'm on works on our APIs and web hooks. And today, in the theme of developer happiness, I'd like to talk about optimizing APIs for consumers with GraphQL. But before we dive into GraphQL, let's start with APIs and, more specifically, REST APIs. I'm curious by a show of hands how many of you have written code that consumes a REST API. Awesome. Cool. How many of you have written your own REST APIs? Dang, awesome. Cool. And how many of you before today have heard of GraphQL? Dang, that's amazing. Okay, awesome. So throughout today's talk, I'd like to use this particular API as a point of reference. This is an API that I put together about a year ago, and it's a wrapper around an NYC open data set for health inspections of restaurants here in New York City. And for anyone who's just visiting New York City for the conference, basically whenever you walk into a restaurant, they're required to post their letter grade, their health rating, or sorry, the letter grade of the last inspection that they received. And so when looking at a REST API, specifically a request for a REST API, there's a few components to it. The first is an HTTP verb or method, and that specifies the operation that we'd like to take against the API. And the second is an endpoint, which is an identifier that allows us to specify the part of the API that we'd like to interact with. So if we execute this request, we'll get back a response that looks like this. In this particular case, this API returns back JSON, and it's comprised of resources. So if we take a look at what one of those resources might look like, we can see that there's a few components to the response. The first are attributes. These are things like the name, the address of the restaurant, the cuisine that it's been categorized as. And in some cases, you'll also see hypermedia. And hypermedia is a machine readable link to another place in the API about information related to the resource. So you can see on the bottom there, we have inspections URL. And if we follow that link, we can get more information about the inspections that the first restaurant has received. In this case, we have a new resource that we're dealing with. So if we execute that request, you'll notice that we get, again, attributes and more hypermedia. And if we follow this link, this is all of the violations that they received during a given inspection. So again, as we make these more requests, we can build the full picture of data that we as clients may need in order to build an application. If we execute that request, again, we get back some attributes and some hypermedia. But if you imagine us as a desktop application, you can see that it takes numerous requests for us to determine the information that we may need as a client, right? We have to make numerous HTTP requests in order to get all the info that we need. And this is especially painful when you're working with, say, a mobile client, which might be working off a super slow connection. So REST APIs are optimized around servers and not necessarily clients. They're modeled around the resources that they return, which makes them general purpose and reusable from client to client. And honestly, that's one of REST's biggest strengths. But the question that I posed to us as API designers, everyone who raised your hand just now if you've written a REST API is, what if we wanted to put our clients first? What if we wanted a better developer experience for the people that are consuming these APIs? So one pattern for that is backends for frontends. It was something that was popularized by Netflix and reused commonly. And the general idea is for each particular device that accesses, say, Netflix's API, they have their own separate endpoint. The only thing is this can become a little bit problematic when you have to start to deal with, like, deep pagination, for example. If you have a complex object relationship that gets returned in this one endpoint, it can be really hard to have to iterate over all of the different, say, restaurants and all of their inspections and all of their violations. And this can be even harder when you have to iterate on that endpoint. Say that there's a new device that was released, a new Apple TV that has a fancy new version of the Netflix application. The older devices that haven't been updated end up getting all of this new information that they may not be using. And this also only really works if you as the API designer are in control of the client and you completely understand the data requirements that that client may need. And what about in the case of a public API where you may not know anything about the data requirements of your clients? Well, that's where GraphQL comes in. It's a data query language for your APIs. So think of it as SQL, which is the lowest common denominator between technologies like MySQL, Postgres, MSSQL, and think of it less as Neo4j, which is an entire graph data store in its own right. So GraphQL is a query language specification. It's been implemented in a variety of different languages like Ruby, JavaScript, Python, and so on. And the language was originally created by Facebook to help with the data access needs of their mobile clients. So here's the hello world of GraphQL. You'll notice right off the bat that it bears some resemblance to JSON. It almost looks like it's JSON, but without any of the values. And that's very much on purpose. And we'll see why in a few. So there's a few different components to a GraphQL query. The first shown here is what we call a selection set. And me represents the currently authenticated user. And for the currently authenticated user, I'd like to fetch the first name, last name, and email. We call these fields. So if you execute this query against a GraphQL server, you'll get back a response that looks like this. In this case, again, it's JSON. And you'll notice that the query defines the structure of the response. And that's a really important part to GraphQL. So going back to our NYC restaurant grades example, we still have an HTTP verb. And we still have an endpoint. But that's pretty much for the similarities with rest end. And the reason that we have to use an HTTP post is because the client has to send information to the server. In this case, it's the query that we would like the server to execute. So if we look at an example for this particular API, you can see that this looks a little bit like the hello world example. But we're now talking about restaurants. And there's a new concept here in GraphQL called an argument. We're basically saying I'd like to fetch the name of a restaurant called Cafe Guia. And an argument as a way for us to pass relevant information to the server. And that way there, the server can modify the response based on the information that we're looking for. So if we execute this, again, we get a response that's very much structured like the query. So let's take a look at some of the features of the query language. The first is that GraphQL is typed. And the type system is a product of your application code. So if we look back to the original hello world example, behind the scenes, there's actually a schema. And it's the schema that GraphQL is querying. We call this an IDL. You can think of it as a database schema. But instead of describing the structure of your database, we're describing the structure of what we can query. So if we break down this query, we can see that each part has a corresponding entry in the schema. The first is me, which returns a user type, which is defined down there below. The user type implements three fields, first name, last name, and email, all of which return what we call a scalar value. It's just a plain old string. So if we look back to our NYC restaurant grades example, here's the corresponding schema for it. Breaking down each part of the schema, we can see that it starts with a top level restaurant right there, which takes an argument, a name of string. And what's really neat about having a type system in place with GraphQL is that you can determine whether or not a query is valid. Right off the bat, if someone sends to you anything other than a string for this name argument, we know that we can just fail the request and say, no, sorry, I don't support that. And the restaurant type, which is defined down below returns both a name and a cuisine, both of which are string. But you'll notice that there's a bang next to the name entry. That is basically a way of denoting that you will always get back a value for that. It's non-nullable. But what if we wanted to return a list of objects? Well, in this particular case, we can use restaurant's plural, which is something that this particular API supports. And you'll notice that the argument here is different from the previous example where we have Brooklyn in all caps. And this query is utilizing a GraphQL feature called an enum. An enum is a way to specify a list of possible values. So if we look at the corresponding schema for this, we can see at the top most level, we return restaurants, which take in an argument of restaurant borough. And what's nice about an enum is that we can specify exactly what's supported. It doesn't make sense for this particular application to take anything other than these five boroughs. And then finally, we return a list of restaurants, each of which has a field, name, and cuisine. So what if we wanted to fetch two restaurants by their name? You can imagine that the response would look something like this, right? Because the query defines the shape of the response. But you'll notice that we have a key conflict, which I'm pretty sure is legal JSON but would totally wreak havoc in Ruby. And so what GraphQL allows us to do is alias field names. And they can be used to rename a particular subset of the query to something else. So if we look at what this may look like as a response, you can see that instead of having our duplicated restaurant field names, now they're using the alias field names. And one more thing that you'll notice about that previous example is that there's some duplication, which isn't great. Name and cuisine is reused. What GraphQL allows us to do is create what's called a fragment. So down on the bottom, we define a fragment, we call it restaurant info, and you have to specify which type that it's defined on. Now once you have the fragment, we can define what the things that we'd like to fetch, in this case, name and cuisine, and then we reuse that fragment with this dot, dot, dot notation towards the top. Now another important part to GraphQL is that it's introspectable, meaning that GraphQL is capable of telling you all of the different things that it's capable of returning. And that means that things like documentation and client generation come for free. Now one tool that utilizes the power of the type system on introspection is GraphQL, which, God willing, I would like to live demo. So this is the part where I ask that everyone make like a silent prayer that this live demo goes well. All right, so let's see if I can get this working. Cool. Everybody see that? Awesome. So this is GraphQL. There's two main parts to it. On the left hand side, we can craft a query. On the right hand side, we can see what the response would be. I'm just pointing this to a local rail server that I have running, and let's give it a shot. So let's say we want to fetch a particular restaurant. So you'll notice as I start typing that GraphQL offers like clippy-like suggestions, and that's because it's reusing the power of introspection. Because the GraphQL server is capable of telling us all of the different things that it can query, it knows ahead of time and it's context aware. So based on where my cursor is, it can offer suggestions. So I'll tap auto-complete and let's say that I'm looking for a particular restaurant. This one used to be my favorite restaurant until I started working on this talk. Okay, so let's say that we want to fetch its address, for example. I hit Command-Enter, you can also hit Play here, and basically with that returns, it's just the address of this particular restaurant. But let's say that I want to add more fields and I don't know what's available to me. Well Graphical has this built-in documentation explorer on the right-hand side, and again this is reusing the power of GraphQL's introspection features. So if we dive into the root query, for example, we can see that these are all of the things at the topmost level that are made available to us. If we dive down into restaurant, you can see this is that IDL-like structure that we were just seeing, where we can take a name argument or a burrow argument and return a restaurant object. So if we take a look at the restaurant object, these are all of the different fields that we can query. So let's say that we want to fetch its cuisine, I'm pretty sure it's Italian. Cool, awesome. So let's try something a little bit more complex. Let's say that we want to fetch all of the restaurants with a name of Subway in the burrow of Manhattan. So now because we're using restaurant's plural, we're going to get back a list of all these restaurants. Let's say that we again want to reuse the address and cuisine and now we get back a JSON response of all the restaurants of Subways in Manhattan. But if you notice, there's some more information that we can fetch on the restaurant type. For example, inspections, and again, this is a whole list of inspection types. So let's take a look at all of the inspections of each of these. Inspection has things like grade, when it was created, inspected at. So let's say, let's get the last time that they were inspected and maybe the grade that they received. Cool, so we get back A's in most parts, B's, don't go to that one. And so we get back a bunch of structured response based on the things that are in our query we've defined that we're allowed to have. And you can also dive in to say violations. This is where all the really good stuff is. So descriptions are basically a list of all the violations that you got in human readable form. Some bad contact surfaces, nobody's washing their hands at that one. Mice, filth flies. I still love Subway. Okay, cool, so let's dive back into keynote there. Cool, awesome. So one of the things that I was hoping to point out with that live demo is the idea that you can fetch multiple resources in one round trip. So contrast that to earlier where we had our desktop client which had to make numerous requests to numerous endpoints to build up the full picture of data that we as a client may need. And contrast that again to the back ends for front ends model where each particular device has its own endpoint. Now each of those devices can utilize this same one GraphQL endpoint. So let's talk about what it takes to implement a GraphQL server. So the NYC Restaurant Grades website is just a Rails app. When we send a request to slash GraphQL, we end up at a pretty regular looking controller. This controller starts by taking the query out of the params, it's just a plain old string, and it passes it to our schema to be executed. Once we get a result from the schema, we render it as JSON and serve that back up to the client that requested it. But in order to do all of this, we need a GraphQL implementation. We need the graphschema.execute part. And like SQL, there are many different implementations. Today I wanna talk about the Ruby one because this particular application is a Rails app and this is Garuko. So the de facto gem for GraphQL is aptly named GraphQL Ruby. It's created by Rob Masalgo and it allows us to define our GraphQL schemas in Ruby. So let's take another look at that restaurant query that we were looking at before and remember that it had a schema definition that looked something like this. It starts off with the root query at the top. The restaurant field returns a restaurant object and it has an argument, it takes an argument named string. But what would this look like in Ruby? Well, let's start by taking just the top level, just the root query and set aside the restaurant field to start. So it would look something like this in Ruby. You can see that we're defining a new GraphQL object type and we set the object's name to root query. This is the DSL of GraphQL Ruby. It's relatively straightforward. Now one thing that I've omitted from almost all of my slides just for the sake of space is documentation. You can use the description DSL down on the bottom there to annotate your schema with various different descriptions and that's how GraphQL was fetching all of its information on the right hand side in the documentation explorer. Okay, so moving on to the restaurant field. What would this look like in Ruby? Well, it's a little bit more complex but let's break it down step by step. We start by defining the name of the field that's returned. Then we have to pass the argument. We define that it must always be a string and again, this is the part where GraphQL can validate that you're always getting sane input. After that, we have to specify the return type and in this case, I'm passing an entire Ruby object. In this case, it's the Ruby schema definition for restaurant because remember, restaurant has a bunch of fields of its own that it can implement. And finally, we have to tell the schema how to fetch the underlying data. And at the heart of every field definition is something called the resolver. In this case, I'm just calling out the active record. I'm doing a restaurant.findby and I'm passing in the argument that was passed by the user inside of the query. And so once we get back a result, the schema starts to look for the restaurant definition and we haven't defined that yet. So let's look at what that looks like. So this is our restaurant type. Remember it had at least name and cuisine both of which return a string. And again, we start off by defining the GraphQL object's name. We can specify a description to have it show up inside of the documentation explorer. But what about this cuisine fields, which returns a string? Well, again, we start by defining the name of the fields. We return, we specify the return type. In this case, it's just a plain old string. There's no more selections that you can make on the cuisine field. And it just returns a scalar value. And finally, we have to tell the schema how to fetch the restaurant's cuisine in a resolver. And so in this particular case, this lower case restaurant is just the active record object that we got back from the previous resolver. We pass those through from resolver to resolver until we end up with the result that we'd like to have. And so this is an important part. The GraphQL schemas are composed of resolvers. And while I used active record in all of my examples, that doesn't have to be the case. The data can be resolved from absolutely anywhere. Which makes GraphQL a facade. It's a facade in front of your database, cache, and services. And in this era of microservices that we found ourselves in, you can talk all of the complexities of an application behind this single, simple interface. And you get to use your own existing application code. One of the biggest misconceptions that I hear about GraphQL is, well, I don't wanna add a whole graph data store to my stack. That sounds like a pain. But that's not quite what we're doing. We're building a query language on top of your existing application code. And that's what we've done at GitHub. So GitHub as a company is almost nine years old now. The REST API that our users rely on, what we call v3, has been in use of six of those last nine years. And to be honest, the API really hasn't changed that much. We add new resources as new features are released, but we strive to keep the least amount of changes possible because every time that we change our API, we're doing our users a disservice. That means that our users have to update their code because it may be broken. But as you can imagine, there's some pain that comes with supporting a six-year-old API. So about a year ago, when we started discussing what the next version of our API could look like, we all had ideas of improvements that we wanted to make. But it wasn't until March 20th, 2016, when the original proposal for GraphQL at GitHub was submitted that the next version of our API really started to take shape. A few weeks later, a proof of concept was done, and it allowed us to query for things like repositories and users, the straightforward objects in GitHub's system. And after seeing this proof of concept, we all started asking each other, if this is what we could do in a matter of weeks, imagine what we could do over the course of, say, a year. So about a week later, a new team was created to take the proof of concept to the next level and see really how far that we could get GraphQL. And about eight months later, we released GraphQL to the public at GitHub Universe. It's a developer conference that we put on in San Francisco every year. And it was an opportunity for us to get feedback from our users on this new API. And fast forward to today, we actually execute over 100 million queries, GraphQL queries every day. And we use GraphQL both externally through a very similar endpoint to all of the examples that we saw today. But we also use GraphQL internally. We use a gem called GraphQL Client, which allows us to exchange a query for these nice, pretty Ruby objects. So you can do things like restaurant.name, restaurant.cuisine. And what this allows us to do is co-locate our queries and our views and our Rails views. And for anyone who's familiar with React, that's a pattern that you might be familiar with. We've also invested a lot of time in tooling, one particular gem that my colleague Garin Turikian here in the audience today built is GraphQL docs. And what that allows us to do is take the result of the introspection query and put it all in this nice, pretty HTML. This is what builds the developer.github.com website. You can see that it showcases all of the types that we have, all of the fields. And it's a way for us to show all of the descriptions that we've annotated inside of our schema. We also practice something called schema-driven development. So before, with our REST API, new features were developed for the UI first. So take, for example, the project board feature. It was released about a year ago. The way that that feature would have been built is we start with, say, the model, then we move on to the controller, and then we have our view until, eventually, we have this feature inside of the UI. Now, after that, we would staff ship it because we're Githubbers using GitHub to build GitHub. We dog food the shit out of the application. And so after we get feedback on all of the staff ship, we might make iterations on this feature and then we release it to the world. And so it wasn't until after that release that work would start on the REST API. But today, all new features are built with GraphQL from the start. And what this allows us to do is build a truly public API, something that's in sync with our features as they're released. But not only does this allow us to build just an API, this allows us to build a true platform, something that's shared between the product engineers at GitHub and our users, our integrators, the people that are building on top of this API. So going back to the question that I asked earlier, what if we wanted to put our clients first? Well, I believe that GraphQL is one way that we can do that. Thank you. If you'd like to find out any more information about GraphQL, you can go to nycrestaurantgrades.com and also graphql.org. Thanks.