 called from REST to GraphQL. So my goal here is not to say, oh, REST is not good. Use GraphQL. It's going to be more of an exploration of how we currently fetch data for apps right now, and how GraphQL can help, and what it does differently. So a bit about me. I'm a wizard working at, wait, what was the word? Software wizard or something. I don't remember. But I'm that at Shopify. We, as my friend Simon said yesterday, he was also from Shopify, we basically make commerce easier for our merchants and help them sell things. Microservices, unrelated slide. I just wanted to have that word there. So I want to start with a simple UI component, and we'll walk through how could we get data to populate that component. So let's take, for example, this is a shopping cart in the GitHub shop. So it's pretty simple, but we still need a lot of data to render all of this. So what kind of data exactly do we need? So we have a cart, probably, cart resource, with probably a total, and it has products. We have the products themselves, which probably have a title, description, price, a bunch of other things. And maybe also product image that's going to contain the URL of the image, any metadata we need. So using reusable endpoints or something like REST, the concept of REST, we have resources, and if you're truly REST, you'll have hyperlinks to other resources. And yeah, basically, you have state, and you can move to other states through links. So how it ends up happening often is we're going to get the cart. The cart resource is going to return us a bunch of hrefs or IDs, but mostly like hrefs towards the products. We're going to fetch those. And the products resources might have links towards their product images. And we're going to fetch those, too. So I mean, that works. We have the data we need. But a lot of users today are on mobile phones, on 3G networks, even worse sometimes, and that's seven round trips. Of course, I'm sure no one here actually does that right in the front end. Nobody does seven round trips. So that's way too many round trips, right? We need something to reduce that amount, especially on mobile and slow networks. So maybe from there, you're going to get, oh, I can use a query param on my cart, and I can expand my association. So please include products in my first request. So that works. But at the same time, you still risk over fetching, because maybe you only needed the price or name of that product, but now you're stuck with the whole resource. So maybe you'll do something even more clever, like a field query param, where you say exactly what you need. But that's still that's only one level deep, right? If you have nested associations, it gets like even like, you kind of have to reinvent the wheel every time. I've seen like X path being used. It's just a little annoying, and there's no convention, right? Everybody tries to do their own thing. So that's one thing. Another solution you might be tempted to use is custom endpoints. So I want data from my cart, but I only want round trip, and I want exactly what I want, nothing more, nothing less. So it's pretty easy, right? I have an endpoint, cart with all the stuff I need. We're done. It's perfect. But that might start with this, but then maybe you're going to have another page in your app, which also a cart but has slightly different needs. Maybe more products, maybe less products, maybe different images. So maybe you'll have a cart version, too, with all the things. Perfect. Maybe you'll have cart with products and images, and maybe you'll have a query param to say how many images you want. Maybe you'll have cart with products and images with price and taxes. Maybe you'll have cart with product with images with prices and taxes, but no description. And that gets like pretty ugly, right? Of course, we don't go that far, but you get the point. So it's kind of annoying. What can we do to have exactly what we want, but still have a solution that scales well and doesn't make the client too coupled with the server endpoints, right? So when a client updates a view, creates a new view, or maybe we have a new product view for another product, or the model of the product changes, every time we've got to update our endpoints in that case, or create new endpoints, and that's kind of annoying. So GraphQL is here to help us. What is GraphQL? Actually, let's start with what GraphQL is not. GraphQL is not a database. It's not some special kind of graph database. It's not a library. You can't just install GraphQL with instant results. It's not language-specific, right? It's not a Ruby thing. It's not a JavaScript thing. What it is is a query language that allows you to fetch deeply-nested associations and select exactly what you want, plus a spec for servers to execute these queries. So it's just a spec, right? So you'll see implementations in Ruby. You'll see implementations on a JavaScript server, really any language. So this is a really simple GraphQL query. It's kind of like the hell world of GraphQL. So what I have here are brackets, selection sets. Basically, tell GraphQL what I want to select on that object, and I have fields inside these brackets, inside these selection sets. So when I send that query to a GraphQL server, what happens? Well, it's like any other language. It's lexed, it's parsed, it's validated, it's executed, and we get a nice response. And the response format is pretty interesting because it follows the exact pattern that you request, right? It's just JSON with the same shape as your request. That's pretty cool. So name was obviously a field on My Shop, but what the hell is My Shop, right? Where does it come from? Is it like some GraphQL magic? I don't know. So it turns out GraphQL models your data as a graph, right? But it still needs entry points to that graph, right? You can't just enter from anywhere in your data. So GraphQL has this concept of query route where you define entry points. Where can I start my query from? So we had My Shop before, but I might do another entry point with shop that takes an ID. It might return the same result, but there are different entry points. This one is like more programmatic way of doing it. My Shop maybe just returned the shop you're logged in or something. So let's take a more complex example this time. So we have new things right here. We don't only fetch the name of the shop. We can fetch complex objects, associations on that shop. So I have the location, which I only want the city address, and a list of products. And I want the name and price of each of those. And there's order by argument, which is a need on. So as you could have guessed, the response is the query with values. So all that's possible because at the core of GraphQL is a really powerful type system. At every level of a GraphQL query, there's a type attached to it. And that type exposes all that object feels, basically. It exposes all the possibilities. So for example, let's take the same query. My Shop here, as we talked about earlier, is on a query root, right? So we have a type query root. And it tells me, oh, I can query My Shop or a shop by ID. And both of those return a shop type. So on the shop type, we're querying name, location, and products. Am I allowed to do that? You can look at a type of shop and see that it exposes the name, location, and products. Name is a simple what we will call a scalar type. So it just returns a string. While location and products are more complex type object types. If we continue here, city and address are selected from an address. And it exposes those fields. Same with products. We have types for everything, right? So that's really cool. It actually shows you, like, you can't query. So it's not a one-to-one mapping with your database graph field, right? It's just like a layer. And you expose only the fields you want to expose. And with the type system, it doesn't let you do otherwise. And you know which types you're expecting. So fragments. Sometimes we want to decompose things. So right now we only have one big query. And you can imagine, for more complex UIs, it gets even bigger. Sometimes it makes a little more sense to decompose those into smaller queries. And GraphQL makes that possible. So let's take a look at the same query again. In, like, we talk a lot about React this year. Just anything like component-based UIs. So if we take a look at, let's say this was my product component in red, it basically only needs what products have, right? An ID, a name, and a price. So what we can do is extract this from the original query and create a new fragment with it. So all we need is name it. So I'm naming my fragment product fields. And say on which type this fragment applies. That lets us do something really interesting by using fragments inside your main query. And that's really cool. Because if you have, let's say, a main root component and children, you can decompose that query into each of the children. And at runtime, when you actually need the data, every children passes its fragment to the parent query. We can send that in one query. When we get it back, we can give it back to children. So this is my favorite part of all GraphQL. It's its ability to introspect itself. And what I mean by that is that every GraphQL server has a special schema field at the query root. And using that, you can actually expose all of objects and fields in a GraphQL server. And this allows us to create really nice tools. For example, auto documentation, right? We can ask for a server, what are your fields and objects? And these fields and objects usually have names and descriptions. Plus, every field they can let you use. So you have free documentation. Code generation, you can imagine if you have some front end code, you might even be able to guess what query they need and generate it because you know what's possible and not. Static validation. You don't even need to let a query go to the server and then get rejected because you know beforehand if that query is valid or not. So IDEs can validate your queries. And they can auto-complete your queries because they know everything about the schema. So with this, we can build awesome tools like GraphQL. GraphQL is kind of a schema explorer for GraphQL. So you can try anything you want really quickly on a server. And on the right, you see there's documentation. You can explore every type and try really any query. And when I saw that for the first time, it's really when I realized this is really cool. So resolving fields. So far, we've talked about fields, object types, but we have actually no idea what happens on a server. You don't just pass in a schema and a query and you get magic data, right? So if we take, for example, the product type, this is an example of how you define it in Ruby. So it's an object type. We give it a name and a description. And we can define fields on it. So fields are really just simple functions in the end. They expose something called resolve. And in resolve, you do whatever you want. So in this case, for a name, the resolve function takes three arguments. The first argument, object, is the parent object. In this case, it'd be a product object, arguments, and a query context that's global to the query. So here, to get the name of a product, it's simply object.name, because it's a product. But like I said, it's not a one-to-one mapping to the database. We can do anything we want. For price, we might add a bunch of stuff and return it. So and with all this, all your fields have their resolve function. So when you have a query, the server is going to turn it into an AST. Walk that AST and call the resolve functions and build the response. And queries can be pretty large, right? So we have to post. And we'll see how it can be a little annoying later. We've only seen reader only, but we can write to. In GraphQL, they're called mutations. And they look pretty much exactly like a normal field. The only difference is that they're only on the root. We have a query root and a mutation root. So they're not nested. They're top-level actions, and they have side effects. But we can still select the return a type, and we can still select what we want from the response. So drawbacks, because it's not like a silver bullet, right? It has to have some disadvantages. So if you implement a GraphQL server naively, you're going to run into a lot of n plus 1 queries. And what I mean by that, I'll show you in this example. So we have a field products, and that's on a shop type. And it returns all the products on a shop. We also have a field image. That one, imagine it's on the product type. And it's simply product.image. So if you run a query to ask for products and their images nested, you might get something like this in your logs, right? So I selected all products, and all of a sudden, images are all loaded individually. And normally, you'll be like, oh, that's easy. Just preload them, or make sure you do where in these IDs. So in GraphQL, it's a bit hard, right? Because resolve functions are all ran in different contexts, and they can even be ran concurrently. So how can you get all images at one time? And for that, a solution is a lot of batching and a lot of caching. And I'm just going to talk about how we do batching and how, actually, most people using GraphQL do batching is by using something like loaders. And loaders, what they do, basically, is instead of immediately returning the product image, for example, we're going to say, loader, I want that image, but don't fetch it just yet. I'm just going to give you the ID. When all the other products in the array have given you your IDs, fetch all of them and return the one I want. So we're batching all these IDs and saying to loader, I only want that one, but I fetch all of them at the same time. So that solves it pretty well. Another issue we run into is HTTP caching. Because we post, and because our queries are not idempotent anymore, we can't really use that, right? We have to find another way. And that solution often is a client-side cache. And this is the part that takes the most time and is the most difficult part to get with GraphQL. But it turns out it works really well, and it allows you to do really cool stuff after. So what we build for GraphQL usually is a normalized cache. And by normalized, I mean, imagine if you stored in your cache the same shape as you received in your responses. Imagine I query all products with their price, and I query one product, ID1, with its price. If I stored it in their original shape, the product with ID1 in the first query and this product with ID1 would be in separate places, right? Because one is nested on their products, and the other one would be nested into a serialized product ID1 key maybe. So if I fetch this first, and another view fetches the product with the second query, we're going to get two results possibly. One's going to be outdated, and one's going to be right. So the way client caches work is we normalize that data, right? So in products, let's say that's my first query, instead of having the image inside, we're actually just going to give it an ID or use its existing ID and place it in another key. So now both queries can fetch that product, that image. So Relay and Apollo are both examples of client-side caches, and they're really great. Since we have all the data on the client, we can now do really cool stuff, right? I have everything I have presently in my cache, and I'm sending a query. I can do clever stuff like seeing the query I'm sending right now. Do I have some data that I don't need in cache already? And we can actually diff the AST from the GraphQL query and what we have in the cache, and only send what we really need, right? So it helps minimize queries even more. Security. So if you read about GraphQL on Hacker News or forums in general, there's always a question, like, oh, you're letting users query your database, like it's the most awful thing ever. But by now, you probably understand that, like I said earlier, it's basically just a layer, right? And we define our schema ourselves. We never expose something we don't want to expose. But there's still stuff that evil people could do, right? Since it can be deeply nested, people can create, like, malicious queries and have, like, I don't know, like a million level of death because it can be circular, right? So there's different techniques to defend that, right? We can use simple timeouts. After one second, if my query hasn't resolved, just throw it in the garbage. We can limit query depth. So I can say nothing in my data is going to be deeper than, like, 10 levels. So if somebody tries to query, if I'm executing a GraphQL query and I'm, like, level 100, it doesn't make any sense, right? So we set, like, a max query depth of, like, 10. We can also use query complexity. So since I'm defining a schema, I can define this field costs 20. And this field is more expensive for me to fetch, so it costs 100. And then we can define a max complexity that somebody can query. That's pretty cool. Future. So, yeah, all of what I've talked about until now is in the spec, and I'm using it right now. But there's also some really cool stuff coming up. One example is subscriptions. Subscriptions are pretty much like a query, a read, except you're telling GraphQL, I want that now, but also as soon as it changes, and every time it changes, I want updates. So you can imagine this could be implemented with, like, WebSockets or service-advanced, but GraphQL doesn't force you to use any technology. So you could implement, if you implement a spec, you can use whatever you want. Def queries are something that are really awesome, too. And the principle is, basically, when I'm rendering some UI, what I want is showing something to the user as fast as possible, right? I want them to, like, feel like it's really fast. So what if, when I query, I could ask the server, send me name and description as soon as you can? If loading the products takes more time, just defer it to later. And we can actually do that with a, that's called a directive with the ad sign here. And it's telling GraphQL, just split up the query, send me the first part that I really need, and send me the other part later. So, yeah, that's, that was GraphQL. So what I really like about GraphQL, and obviously REST is still, its simplicity is just so awesome, right? So GraphQL might not meet the needs of everyone if you have, like, a really simple app. If you have a lot of caching and you don't want to use, like, a complex client app, REST might still be the perfect choice, right? But if you have, like, complex UIs, like, we usually have these days, it's much more complex than before, right? Like, before it was a static page and it's basically just what I have in database, I just show it. Right now, we have, like, much more complex and much more nested objects. GraphQL is great. So GraphQL exposes all the possibilities that a server can do, and then clients just choose what they want, right? It makes it really simple. If you have an Android app, if you have a web app, if you have other servers, they can all talk to GraphQL in the same way, and you don't need special endpoints. Thank you. If HTTP2 becomes mainstream, does GraphQL still have an edge in terms of reducing latency or mitigating roundtrips? Very good question. I think it does. Maybe less... Maybe roundtrips are going to matter a little less, but still being able to select the data you need and reduces your payload and all that query depth I talk about and having really intelligent client caches are what really makes it shine, I think. Okay, how do you prevent the client from making complex queries that would take forever to run? Is that possible? Yes, it is possible, and yeah, I talked about it, right? So basically, you can limit by having a timeout that's the simplest way, and I think that's what Facebook uses if I'm not wrong. It's so basically, after one second, like I said, you just drop the query if it's taking too long, a query depth and query complexity giving us core to each field. Does Shopify actually use GraphQL and how hard was it to implement over your data? So we started playing with it. I don't think I can say if we're using it for sure, but we're definitely played with it. We have some open source repos, GraphQL Batch, which the loaders I was talking about. That's some people at Shopify build that and it's really cool. Wow, you have like so many questions they keep going. All right, when the product is updated in the database, should we reset the cache or is there something in GraphQL doing that thing automatically? Right, so caching is, cache expiration with GraphQL is still not set and it's for me, it was kind of the hardest thing. So on the web, right, we can always trust that maybe someone's gonna refresh eventually, but if you have a cache on like a server because GraphQL could run on your server, how do you expire it, right? So I've played with TTLs, TTLs are like, they're really the only way I've seen like work well to like expire in time, but it's hard, it's a hard problem. How does GraphQL compare to Falkor? So the Falkor and GraphQL, they are similar. They basically solve the same problem. GraphQL has its own special query language. And the main thing is Falkor doesn't have that type system that GraphQL has and I think that's the edge I like more about GraphQL, it's really forced, like the strong typing, but Falkor is awesome too. I can keep them coming, so just tell me when you want me to stop. Sure. How do you keep the reference to the deferred part of the query? To the? The third part of the query. Oh, so when we split them? Yeah, yeah. You don't really need to keep reference. So you split it and you, so you can ID it first or you can just split it and when you receive an answer, any answer, you just put it in your cache. So cache is always like the single source of truth, so you don't need to know, like, oh, I split it so when I get it back, I'm gonna put it here. You just, you result, like when you get data, you just put it in your cache normally. And I'll ask you one more. Does GraphQL have a hard dependency on a particular type of backend database? No, that's the really cool thing. So remember I said, like, resolve in fields are just like functions? Well, these functions can do what the hell they want. Like, one field might get the product from memcache, another field from Redis, another field might do a call on REST API, another field might be from MySQL. So you really can do anything and it's a great way to, like, interface if you have, let's say, like, a GraphQL and behind that you have, like, even REST APIs or other GraphQL APIs. Any backend does it really. All right, thank you so much. Thank you.