About this talk
Dive deeply into GraphQL subscriptions, and see how to use them today in real-world applications with Apollo Client. We'll explore the concepts behind subscriptions and how they work on a full-stack level. By the end of the talk you'll have a good understanding when and when not to use GraphQL subscriptions and what the future of real-time GraphQL might look like.
Alright, this should work in a second. So this talk is also driven by passion, but hopefully not too useless, so today I'm going to tell you a bit about GraphQL subscriptions, there's a lot of hype and movement currently around GraphQL subscriptions, and from my personal experience the whole area around GraphQL subscriptions is pretty ambiguous or let's say unexplored and unknown for the most, so I want to shed some light on that and kinda get everybody on the same page. What are GraphQL subscriptions, and what is real time GraphQL and all of that. So yeah I'm quite happy to not giving a introduction to GraphQL today but I can directly dive into some of the more specifics so that's great. So the structure of this talks going to be, first I will present some concepts behind GraphQL subscriptions, also showing kind of the current state of less official and official specification for GraphQL subscriptions. I'm going to show you how you can use GraphQL subscriptions today with Apollo's proposal, both from the client side and from the service side. So I've picked this order that we see how to set it up and how to configure everything, then we are going through a demo where everything is hopefully working, and then I'm going to tell you a bit about how the whole thing can work on the service side and I want to share some resources with you. So as Gerard said, and thanks for organising this, this is great. I'm one of the founders of Graphcool, which is a serverless GraphQL platform, so we are starting out building a similar platform, like Para or Firebase based on GraphQL, but we're having quite a bit more ambitions towards combining that with serverless technologies like AWS Lambda and so on. So if you're interested in that, come and talk to me afterwards. Yeah and in general I really, really like cutting edge technology, that means mostly I write a lot of issues because stuff doesn't quite work yet but after all that advances everybody. So let's dive into some of the concepts. So I think what most people are familiar with are GraphQL queries and mutations. So this is a very straightforward pattern that you send request, the server does some work, and you get a response back. But how to, and I think I don't have to dive into all of the big benefits of why GraphQL is great and solves a lot of problems, but how do we move on, move ahead from this request response pattern to make it work in real time? So how does real time work and how does real time work today? So a couple of familiar solutions may be firebase, I think there are a lot of great meteor developers out there who use the reactivity layer of meteor but how can we achieve the same thing with GraphQL? So if you haven't seen Rob's talk about GraphQL subscriptions, I can definitely recommend that to you. So he categorised the current state of GraphQL, about GraphQL real time APIs into two parts. One is pull based so a current way to make GraphQL kind of real time is based on based on a pattern I think everybody's is familiar with which is polling has a lot of, it's pretty intuitive and simple to understand and I think what we shouldn't forget is this is, in many use, in many cases actually a pretty good and solid solution. So for example if you know the interval when data changes or if you don't need to get the new data really instantly, then that's a really great position to start out since you can just do normal GraphQL queries and you kind of get a real time functionality if you enter some polling. In case that is not enough, there are two other concepts currently evolving. One is, I think, the lesser known which I'm not going to cover today. It's called live-queries. So I'd like to think about live-queries as intelligent queries, so they, they can know when to, when to, when they need to update themselves. So again watch, I highly recommend watching Rob's talk for that. He's doing a great job about explaining this. What I want to talk more about today are event-based subscriptions. So the term event-based subscriptions is mostly used to make it more, a bit more explicit what subscriptions are. So the idea behind it is that you subscribe to a certain kind of event and as soon as this event happens, something happens in the server, you have already established a connexion, the server pings you, hey this event has happened and the cool thing about GraphQL subscriptions is that you can tell, let the server know, I'm interested in these, this kind of information by specifying a GraphQL query and you get back data of the shape. So we're kinda combining these, the best of two worlds. One is real time and one are GraphQL queries and we get event-based subscriptions. So what's important to know is if people have already built real time web applications with websockets then maybe you're used to like writing and reading data both ways. GraphQL subscriptions are ready-only so that's I think important to notice. So the concepts behind GraphQL subscriptions. So I've called them channels here but it's really, maybe there's a better term evolving, what I mean by channel is if you look at a GraphQL query, the GraphQL subscription query, what I've highlighted here, called a message, this is my channel. So as soon as something happens about the event message, I want to get an update. So what I've phrased here with queries, fragments, and variables is basically that all of the known concepts behind GraphQL queries and GraphQL mutations, you can reuse that in subscriptions which make it really intuitive and easy to work with. Then there's also the concept of a connexion. So a connexion, imagine a client and a server, they need to establish some kind of connexion, so the connexion could be via websockets, it could also be via other protocols. And inside of a connexion, you'll have then the concept of a real subscription. So you establish a connexion and then you can say I'm subscribing to the message event or I'm subscribing to their host like event. So it's important to know that you establish one connexion and you can have multiple subscriptions in this connexion. So I think this is what everybody is kinda used to. You have your server here, maybe you have your old rest APIs somewhere hidden in your domain layer, you wrap it with GraphQL or you've built an entire GraphQL server from scratch, and you also have your client, and they're interacting via requests and responses. So how does Graph, how do GraphQL subscriptions fit into this? So you have, so let's practise on. So here we still have the traditional GraphQL server with requests and responses. And additionally the client also connects via, by directional transport, like let's assume that are websockets for now but it can be really much anything. So the client established another connexion with a server, doesn't have to be the same server, and here the client can subscribe to multiple event-wide subscriptions, and these subscriptions get fed new data, by, for example, if the main layer tells the subscription server hey something has happened maybe somebody liked a post or has written a comment and the user has established a subscription, via connexion a subscription so the subscription server knows about this so he can push the message through. So this is kind of the, a simplified architecture. When I'm speaking about GraphQL server implementation, how we do it at Graphcool, we can translate that to our implementation. So a bit about the history, so maybe some of you know a GraphQL server framework called Sangria, it's I think one of the most mature GraphQL implementations, also one of the earliest ones, it's written in SQL, it's absolutely fantastic, we're using it in production for more than half a year now and it's fantastic. so I think if I'm not mistaken Oleg the author was one of the first people to really attempt implementing GraphQL subscriptions, so there was no real public opinion yet about what GraphQL subscriptions will look like but he just wanted to have it, so he built it, which is awesome, so that wasn't actually built on websockets but on service and events. By now he replaced it with Apollo's proposal and Apollo's proposal we will look more into right now. And luckily there's also, since the last couple of weeks, the official GraphQL RFC process for subscriptions so I highly recommend everybody to read this through and give feedback and hopefully after this talk all of us have a better understanding that we can give better feedback to this current RFC, since this is very much shaping the future of this protocol. Yeah and I'm, in general, I'm really excited about that this is the first RFC for GraphQL and as GraphQL is entering this new stage of openness and getting back more into the hands of the community which is awesome. So today we're gonna cover mostly the Apollo's proposal since this is currently available. I think it gives us a good understanding of what it could look like, how it might need to evolve, and at the same time how everybody of us can use it today. So the proposal is based on websockets, so again the connexion between the client and the server. In this case, they've picked websockets because it's just openly available, people are familiar with it, but it could kind of be anything. They're trying to make it not bound to Apollo client or any other client in specific, but in fact they're trying to make it as open as possible that it works with any client and any server implementation but at the same time we have to see this is, we are still exploring here and we are trying to learn as much as possible. But I think they've already come pretty far. So let's dive into some of the technicalities of this. So the graph, the protocol proposal has message types. So this is kind of like yeah the protocol building blocks of what a communication between a client and server looks like. So we are going to see this in action right away. I just wanted you to see this first. So when a client establish a connexion with the server, he, the client creates a websocket connexion, sends a first message with a type in it, then the client can send a SUBSCRIPTION_START event together with a GraphQL query and the same, and also after all of the work is done, the client can send the subscriptions end event. From the server to the client there is a response to the INIT event, which either INIT_SUCCESS or INIT_FAIL, and also for SUBSCRIPTION_START, that could've failed or succeeded and then the actual important thing is the SUBSCRIPTION_DATA, this is actually when a message comes through. So this is how it looks like in the network tab of chrome, so we're just, I've just like reloaded the page, there's an INIT event, then INIT_SUCCESS, I'm sending a subscription, SUBSCRIPTION_SUCCESS, I've waited a bit until a KEEPALIVE event comes in. And then there's actual data coming in. We can explore that and this is, this is just JSON coming back. Stopping at subscriptions and yeah that's basically it. So again if we are looking at these event types here, this is basically besides the failed event types, these are all covered here. Alright, so let's take a look of how this can work on the client side. So this is an overview what Apollo shared once they officially released their proposal. So together with their proposal, they've released a tool called subscriptions-transport-ws so this is what they hope everybody will build into their GraphQL client. It is already compatible with Apollo client, we'll see what emerges for Relay and other GraphQL clients, but this already shows which kind of building blocks are necessary, excuse me. So this tool works across all frameworks and GraphQL clients, it's fairly lightweight and cares about establishing the websocket connexion. Can be used both client side and server sides and it can be, for example, with the Apollo client, it can be used roughly like this. So here we are importing the subscriptions client in a ??? Method, here we're just importing the normal Apollo client, here we're creating the network interface for the Apollo client just with the normal http GraphQL endpoint. Here now we are creating an additional GraphQL client via the websocket connexion. So we have a separate endpoint, again if we remember the architecture diagram, there's a GraphQL http server and there's a subscription server, so there are two different endpoints. Here we're just, this is how they created the API for Apollo, we're generating one combined network interface and initialising Apollo client here. So does that make sense to everybody who's used Apollo client already? Alright great. So this is basically just the set up and this is how you can actually instantiate a subscription and yeah, subscribe to the subscription. Similar to how the rest of Apollo works, you can use set extremes here so the API looks like this, we have Apollo client, we subscribe to more, or we adjust getting more subscriptions into the Apollo client. Here we're having the normal GraphQL query, we can also execute in GraphQL we can send long variables, which we are not doing here, and this is actually the important bit where we are getting called with new data coming in for every event. So before we are diving into the demo, there are a couple of cases which is yet unexplored, so for example, with normal http servers you can send http headers and so on for authentication and all these sort of things. For the websocket subscriptions, for the websocket subscriptions there is currently the connectionParams option, so here you can, for example, set authorization data or some kinda meta information around this connexion. So the app we are going to look into is a world map combined with a chat. It is written in React and the component structure looks roughly like this, we have a app component, that has a world chat component, and in this world chat component, we have the map and we have a chat sidebar and where I've put these record emojis, this is where we are actually doing the GraphQL subscription. So just that you have a feeling for that yet. Alright so I suggest we are looking into some code. I'm not attempting to write live code here, though. Sorry. So here, can everybody see it, is it big enough? Alright brilliant so again this is how the setup looked like, all of this is also open source, I'm going to share the links with you afterwards so you can try it out on your own. So here we're importing the Apollo client, here we are importing the subscription client, and yeah we are instantiating the subscriptions client right away here and we're instantiating the normal GraphQL network interface here, combining them and creating the Apollo client and then later on we are basically just passing in Apollo client into the React context. Here we're having the world chat, in the world chat we are looking at the queries right away. We are having the, basically a Google map component which displays some pins Again I'll show the real demo in a second, and we're having a chat bar. So let's look into how that, how that looks like. So this is basically it. We have a map here so you can actually go to this link and chat with me right away if you want to. But we can also chat afterwards. Right and here this actually works with GraphQL subscriptions, we can see how this works, I've filtered here for GraphQL, for websocket, websocket connexion. So here we see INIT_PAYLOAD we are sending two subscription queries here, so ones where messaging, we're listening to what's called a message, and ones we're listening what's called location. And whenever something changes about this, we're getting events in. So here for example, I already got a location update, oh there are new people coming in. So maybe somebody's answering, but yeah this is roughly how it works. So I think what's now also, yep, really works then. Well let's move on. So in here in this red component, we are basically initialising everything, so for that all of these loads, we don't wanna like open this a year ago and then waiting until all of the data is there, but we also want to initialise the whole view with some data. So we're doing some normal GraphQL queries at the beginning, and then we're subscribing to the new data coming in or to data changing and we're combining all of that. And this combination happens, for example, for the chat component that happens here as we're subscribing to messages, we're here subscribing to new created messages, so this is just the Graphcool API, you could, if you're building your own GraphQL back-end you can design it however you want, but here you can for example filter like newly created nodes or updated ones and so on. So here we are listening for every node, we are interest in the ID and the text, when it was created, and by whom. And here we are getting the data. So we are passing, we are getting out the new message and basically just append it to the list of old messages, we are here returning the new state, this is then added into the, this is then passed back into the React component and yeah so you've basically closed the loop. So I think this somewhat gives you an overview how you can use GraphQL subscriptions of course you can, it's basically how complex you wanna make it is up to you. Here is basically, in this reducer, it's up to you what you implement there, the concepts behind GraphQL subscriptions are really simple. Right so going back... Alright yeah and, ugh, same thing happened last time. Okay there you go. So yeah here I think the live demo, some of you already found it, here on Github on graphcool-examples, you can find all of the subscription examples, but I'll also put up the slides later on. Right so does the client side make sense to everybody? Perfect. So let's have a quick look into the server side of that. So I'm not going to go too much into detail how you can build your own GraphQL server, since there are just so many options and I'm also have some vested interest in you not doing that. So... But what Apollo basically suggests you do, which you can do, which is also pretty easy in the beginning, is that you can use the server part, also the subscriptions-transport-ws component, and you use that in your server application and they already provide the GraphQL subscriptions module, which you can use with one of these subscription engines, kind of, so I think this makes a bit more sense after the next couple of slides. So first we need to think what does the server actually need to do? So most importantly, the server needs to know when to send a message. And this is where it already gets pretty complicated that you need to, you need to keep track of who should get a message by when. So if you're talking about a normal http server, if you're if you architect it in the right way, then it should mostly be a stateless server. That is not the case for subscription servers since you always need to take, you always need to keep track of which clients are currently subscribed to and what, what are they actually interested in. The server also just needs to host the selected communication protocol, so that might be websockets or whatever protocol you're using, and the server also needs to implement business logic. I'm going to dive a bit more into what business logic in that context means afterwards but that is far from trivial and I think one of the hardest problems Facebook is tackling was when they decide between GraphQL subscriptions and live-queries and so on since this is absolutely not trivial, but more after, about that in a second. So if you're going back to this architecture diagram here, let's break that, let's break that down a bit and see how we build at Graphcool. So I'm just now going to talk about the green part over there. So imagine this. You have a bunch of users, we have seen we are creating this websocket client, and this websocket client needs an endpoint for the websocket server. So this is what we have here, this websocket server, a client can create multiple connexions even if for whatever reason and they can have multiple subscriptions per connexion. And then this is basically everything the client needs to take care of. The next level where we have to keep track of how things are working is how we map the actual subscriptions to the events. So we have what we call channels which are basically buckets of subscriptions. So for example we have two, maybe two users who are both subscribing to the message event. So what we are doing is, I think this use case doesn't really represent it, but both are subscribing to the message event, then there are two subscriptions connexions, but internally for me both of these subscriptions are listening to the same event bucket. So we are doing all of this mapping and bookkeeping internally. So for the internal part we also have the subscription server, which is kinda taking care of receiving new events coming in from whatever event sources, so one of the event sources could be the API server. So imagine another user running a mutation, this mutation changes data and the data the other users are interested in. So for example they are updating some nodes, deleting some nodes, and so on. So the API server, triggers, sends some triggers to the subscription server, the subscription server figures out which of our current subscriptions are actually interested in that, propagates it back to the websocket server, until the websocket server pushes it back to the user. So this diagram is a pretty simplified diagram of how it works for Graphcool, so feel free to ask me about specifics about this but yeah that's not as simple as it looks like. So all implementation is based on Akka Actors, so this is, if you're familiar with Erlang Actor Model, which is used in telecommunications systems, this is what we're using here as well since it scales really well. We are having these buckets per subscriptions and so the subscription buckets per channel, sorry, and in our domain we basically create pre-defined channels based on every type, and based on every mutation, so we've seen for the, the subscription we previously subscribed to was message, you can filter by mutation type, whether it's created, updated, or deleted. So I want to share some of the challenges we ran into, so first of all, there is a tonne of infrastructure involved in here to make this work and to make it work reliably. When we are talking about real time, should be somewhat fast, so that also comes with their own challenges, also needs to be efficient, we ran into all sorts of memory leaks, which is also pretty tricky to solve that. Oh yeah, it's so important that I put it up twice. And I think what's one of the biggest challenges here is that it's actually stateful. So it's not as easy to scale that you can say like let's put a, let's pull up new servers, connexion graining becomes a lot more difficult. If you're implementing your own subscription server, you'll face all of these challenges, so yeah but feel free to do so. So my last slide about the server side, business logic. So by business logic, there are a couple of things you might want to think about. One is when you're talking about Facebook scale events, then it's not just like the simple chat application here where you kinda can assume alright there might be like 50 users and like they are not creating too many new events, but if Justin Bieber posts like an image and there's only like thousands, thousands of comments and likes flying, you don't want to send like a single event to the client all the time. It might not have the bandwidth, or the client's device might not keep up, so you need to think about throttling, you need to think about offering, maybe you don't want to send all of the events but at the same time you don't want to prioritise these events, you might want to send some aggregated events instead, so there are a lot of things to think about while implementing that. And that's also fairly unexplored and I think also all of this needs to be considered, when we are talking about the RFC process for GraphQL subscriptions and what the future of live-queries could look like. Right that pretty much brings me to the end of this introduction to GraphQL subscriptions. Here are a bunch of resources I found interesting. Most importantly the current RFC. Here is also another great very informative issue about live-queries, so yeah I hope there will soon be a talk about live-queries as well and maybe in a half a year we are also having official RFC and Apollo may be implemented the first version of live-queries already but the whole future of real time GraphQL is really, really exciting to me. Here's also a bit of a older blog post but still really, really interesting to read how it's not as much about Relay actually but more about the motivation, why subscriptions make sense and live-queries are not the only answer to all problems, so I highly encourage you to check these out. And also if you want to see how this live world map is built, there's also a YouTube video here. Right so you already mentioned it, we are part of the team who's organising GraphQL Europe, we are super excited to not just have all of the momentum in Silicon Valley about GraphQL but also to have it here in Europe, so we are organising GraphQL Europe, which is the first GraphQL conference here in Europe actually, it's going to be in May 21st. Our CFP is still open so we have a lot of great talk proposals already but if you're, for example, want to present how your company uses GraphQL internally or maybe how you're transitioning from REST to GraphQL, how you're abusing GraphQL for one specific thing, feel free to share that with everybody. And yeah also please come, tickets available, and yeah so if you have further questions and you cannot get a hold of me with the chat world map thingy, you can also find me on slack. And yeah that's basically it, so I think there's a bit of room for questions, right? Cool yeah thanks. - Okay so we have some swag to give away, so if you have any questions this is the right moment. - Also stickers, by the way, so feel free to ask me about these. - Okay. - Thanks for talk, very interesting. I got a question about server workers and GraphQL queries. Is it work like nicely I guess. - [Johannes] Sorry? - So - [Johannes] Server workers, service workers. - Yeah and GraphQL staff together. - So we have a couple of customers who are using, who are doing this. We haven't really seen it in scale yet so maybe that's, maybe Facebook can share some insights about that. Right right not surprising. so I can share a couple of prototype implementations with you, we can't really say how that works at scale since service work is, when it comes to that, also fairly unexplored still, but we know that it works. - [Man] Thanks. - [Man] Okay, another question? - I was wondering if you could talk about a problem that we had great fun solving which was handling events that occur after you've made your query but before you started your subscription. - [Johannes] Alright, one more time? - So you make a query, say like give me all the messages, and then you get your response and you make a subscription for new messages. - [Johannes] Right. - How do you handle events that happen in that period before the subscription is active? - So that basically depends on how you implement your back end. This is also part of the business logic, so based on your domain, you might want one behaviour based on another domain, you want to have another behaviour, so that really depends on how you implement it in your back end. - [Man] Okay so just application dependence. - I think there is like a good ground rule where one use case fits most people, and this is what we are building at Graphcool. But there are also very specific use cases you might want to implement yourself. - [Man] One last question? Sorry I don't know who was first. Maybe you, okay. - Hey, great talk, great work on Graphcool. Lot's of great examples that you used on blog and on the platform. I have a question, have you considered or have you thought, have you have any thoughts about implementing subscriptions on top of third party real time services, like Pusher, for example. - [Johannes] For our platform? - In general. - So I mean in general if you want to not use our platform then nobody holds you back to just build that, when it comes to our platform, this is where we want to leverage serverless functions that you can map any kind of data source when any kind of event happens and bind that into your GraphQL schema and into your GraphQL system so that you have any kind of event, external event source so that might be a Pusher event, and you implement our serverless function, which triggers something and propagates it into your GraphQL, into your GraphQL API. - [Man] Yeah I actually thought more as a transport layer for the GraphQL subscriptions. - Ah, alright alright alright, so currently we're mostly focusing on the current websocket implementation there is at the moment, but if other implementations for the transport layer really pick up steam, then we'll probably also provide support for that. - [Man] Thanks. - Yeah. - [Man] Well I think that's all, thank you very much for your questions, and thank you Johannes. - Yeah thank you. - [Man] It was awesome.