 Absinthe. I hope you can take a look at our website which we've got linked down there on the left which has some guides and other information on our community page is how you can reach us. We've been using GraphQL and Absinthe in production for about nine months now. It's been a really good experience for us. Both as backend developers, mobile developers and front-end developers and so we've been really happy that Cargessons have been willing to encourage and support this. Before we jump fully into GraphQL however, I want to talk a little bit about why the thing that drew me to Elixir was how I felt like when I sat down to solve a problem the code I was writing was about that problem which is to say there were abstractions the language and platform was giving me that could let me focus on doing whatever it was I had needed to do to solve the problem and it wasn't cluttered with mechanics of dealing with you know some of the underlying mechanisms and what struck me then and continues to strike me today was how well those abstractions fit together and as I wrote more Elixir code and better understood how it and the features we get from Erlang work, I realized that the reason they can do that is because they're all built from these really composable underlying building blocks that we get from the beam. So instead of giving us like supervision trees or instead of giving us pooling as like a feature, it gives us the tools that let us build those things and extend them and I think it's part of why it's been such a successful system over the decades that people have been using it. I think that's just like a one characteristic of good systems in general is that they give us the tools to build tools and they give us features out of which fall more features. So and I'm gonna argue that I think GraphQL is one of those things but it's probably best to do that in light of where we are. So let's look at REST and let's look at one particular thing about REST which is how REST models relationships and hierarchies. These things are sort of basic to data whether it's like users that have you know friends or it's even just in a user how it's the the name as property of a user relates to relates to the name we have. So the request side you get basically like a linear path and that's all right. On the response side there tends to be one of two camps that happens. You've got the the sort of link to things camp where data that is immediately associated with the the resource in question is presented to you but if you want information about an associated resource you have to go ask that thing. This is one of only only one of many ways that that these links end up being used but the general idea is that if you want to know something about a resource generally speaking you're gonna have to go follow the link to it. This kills the mobile. Requests on mobile are expensive. They're expensive in terms of time because the the latency characteristics of mobile networks are they're expensive in terms of power consumption because if you're having to do a bunch of requests the radios have got to be on the whole time. They got to be operating in ways that they don't need to be if you're not needing to request more data. So what this tends to lead to is the other camp of rest where when we want associations we serialize all the things and that's what we get. We tend to get this in the browser too because honestly browsers aren't super good at making lots of concurrent requests either there's a lot of limitations about how many they'll do to a given domain and stuff. So the problem here is that we no longer have an API of resources but an API of bespoke data views for each and every use case and so this on the back end leads to a wide proliferation of code because you've got basically generally custom code for each and individual use case and there's also this implicit client server contract that's formed because even if you're following less best practices and this is the mobile thing so you got slash mable v1 users that just tells you that what you were getting from that API last week if they're following the right rules you should still be getting that today. It doesn't actually tell you what data you need from that API. It doesn't tell you what data your client expects from that API just that it hasn't changed. We need to be in that and so we're going to look at some of the tools that GraphQL gives us to answer these kinds of questions and we're also going to look at how those tools come together to produce some ridiculously awesome features and we're also going to look at how our implementation absinthe brings us to you and what it means for elixir developers and users of elixir libraries. So as we saw relationships and hierarchies are one of the main things we're trying to solve. So this is a GraphQL query and you'll notice that we're getting we're going to be declaring exactly what we want out of the response and this is our response. There is this exact correspondence between what we asked for and we get nothing less and also nothing more. This is really great for mobile in that you can ask for a lot of data and you'll get back in one request exactly what you want but you also won't get back often asking for lots of data can be you're gonna get stuff you don't actually need and this waist bandwidth it wastes it's it's unnecessary. So the structure of the query itself tells us a lot about about the client server contract and we've been able to make it explicit. We actually know even more because of another characteristic of GraphQL where all the data going in and out has an associated type and this type system in addition to holding some invariance about this stuff that is actually really nice is also going to be a powerful enabler of a bunch of features we'll see later on. So back to rest real quick. Rest is basically untyped. So we have a rest endpoint and we're gonna get events and we want to get it on a particular day and maybe at a particular location. Considerations which of these are actually valid is is the date a valid shaped date with that location ID you know often your query parameters are smart enough to turn like a number into like the text for into the integer for or sometimes your database wrapper will be okay with that too but suppose the client makes a mistake they pass the name in for example of the location they're looking for not the ID actor will blow up which is probably the right answer because you you're not gonna just you you can't turn like Disney World that's not an ID that doesn't make any sense active record will make it zero and carry on neither of these are what you want from a client perspective what you would like is something that says hey don't do that that was wrong do this thing instead so just to sketch you know code you would need to do this stuff you've got your like white list of things you're gonna go through the parameters and pull out each of the values and then for each of these things you might need to do some custom handling on one of them to make it a date or whatever and look I'm my head's not been in the sand I know there are tools to deal with this people are using ecto change sets they're using there's like the JSON API thing Bruce Williams and I wrote VEX almost three years ago I think this Saturday to do exactly this thing data validation tools exist I do not have time to do a one like a one-on-one comparison them in this talk well I think you're gonna see those that the kinds of invariance that GraphQL is gonna let you articulate and that it will hold for you about your data are kind of standing a class on its own I do hope to have a blog post out about that soon kind of going into it in more depth so this is this is the controller callback basically that you get by hitting this API endpoint if you notice the irrelevant part of the code is in the bottom right hand corner where we finally call event dot list on our filters that's the important part here and if you're writing GraphQL this is what you get to actually do so up top you have the equivalent the GraphQL query that would be analogous to our REST query we're passing on a location and we're trying to get it on a particular date but our code because GraphQL has held some invariance force we can just filter on those things now how is this enough it's enough because what we end up doing is we have a schema so this is the full story and so to remind you of our geography up top we've got our our GraphQL query that middle is just exactly the same function we had before and then this bottom part is elixir code written with the absinthe library where we have a correspondence between we have field events and that is what gets just what that's what describes the query we have up top and then we have the arguments that constitute valid parameters to that field our date allocation our name we also have a return type specified for that field that's the list of event thing we'll get to that more in a second so what this has done is it actually inverts the control flow that you often see in a controller controller hands you invalid parameters or certainly parameters about which you don't know very much and you have to hand it off very often some kind of tool or library that will validate it return information and then you can kind of carry on GraphQL is the only way around where you articulate the invariance that you're going to have hold on a field and then if it only if those things actually obtain what it call your code and you have to worry about it so we look at a couple of these types really quick to see how that happens our date type our string type and the event type so it's worth pointing out when we if we were to look at our date type from the filters there from our def events it's actually a full-blown calendar struct at this point like you don't have to worry about the fact that it sort of represented up as a string up here at the top this works because we have a date scaler scalars are just value types there are things like strings numbers dates etc and they all have a parse and a serialized function parses job is to take it from the external representation like a string and to make sure that there it is a valid internal representation for that thing so if it if that function returns okay and a date time struct you agree your function is going to get a date time struct if it doesn't it'll generate some relatively impressive air handling we'll see later that'll get returned to the client the and then the serializes for going the way so if you return something that has a date in it that handles putting it back into the external representation here's a string so there's no special casing here like our implementation ships with strings integers other things floats because everyone uses them but all the tools we use to build types are exactly the tools that you have when you use absent and this gives you basically all of all of that power to use for your own domain lastly this is our event type you'll notice by the way throughout we've actually been able to stick documentation on this stuff and you'll see where that comes in here in a minute and on the date field location field and name field not only do they have a type they have a thing where we have a non-null around that type so we're declaring things that must hold not only about data comes in but data that goes out and this turns out to be not only super useful for those of us who are back-end developers to catch mistakes problems or just make sure we don't have to worry about certain things it also turns out to be wildly helpful for clients because clients can figure out stuff about our schema as well so this is another graph ql query that we can make and it asks the schema to tell us about itself so this will return just some basic type information because it's a this is not special case either we ship with these introspection types because everyone should use them but if we didn't you could make these types that return information about your schema this is what I meant by like graph ql giving us features that fall out of which fall further features so what falls out of this is probably the coolest the coolest API exploration tool ever in that we have this thing so this is if I can figure out where my mouse is there it is this is a little piece of JavaScript that we when you run it it hits the server with this oopsies that's gonna be hard to see slightly more complicated you don't have to worry about the details of it but it's this same underscore schema thing we've been before it's just a bigger query so we can get more information and what we get with that is an overly zoomed in web browser there we go so we get amongst other things documentation so this is a relatively silly little example that represents the Star Wars universe you tend to see it around the the graph ql community and so we can just go splunking basically like hey there's this empire field it returns a faction what a factions hey look if you get I factions will always have an ID this this exclamation point here means it's not null these are things that clients can just know on an automatic way about your schema more than just self documentation though this tool actually lets you construct graph ql queries so you can start typing and hey it auto fills it in for you this keep in mind this piece of JavaScript knew literally nothing about our schema until it started running and ran the introspection query you can get things like the ID and the name and if we make mistakes like ask it for a field that doesn't exist we run this we're gonna get back two things that I think are very important to know one is this error message that talks about hey this isn't valid and the line information which is super nice hope to bring you call them information soon Lex and yet don't have column information so we don't have that yet but we also actually get still the name and ID so the graph ql spec not only spends a lot of time talking about what constitutes an error but how the server should behave when it runs into an error and the answer generally is like if there were children off of this like this these will not show up because its parent is bad therefore doesn't make any sense to talk about the children but siblings are still good it will still try to get you that error and this helps provide kind of consistency across the the experience of using graph ql servers so anyway introspection it's cool the introspection gives you actually a lot more than just than just like query exploration so here we've got like a basic response and the most is two things that return something that's basically an organization are usually as a primary organization and our location as an organization just looking at the JSON blob we can't really know for sure that these are actually the same thing but if we can introspect on the type and there's certain invariance held about how you return IDs for things of the same type those ridiculously cool caching libraries that are being built that operate on graph ql servers because they can use this type information to do really really intelligent and granular caching about values I do not know how they work and we will not be going into that but it's the kind of thing that can happen in a generic way because of how much clients can figure out about the server with which they're interacting so we also have some really really neat features that are developing on the query side of the equation as well and this is kind of making it's really getting into kind of experimental territory both as far as absence absent specifically and the graph ql community in general so in this query you'll notice that we have on our response we have our feed no stories and the author and message for each of the stories but the comments don't seem to be there and that's because the comments had what's called a directive applied to it the defer directive and suppose you have a client interface of some kind where the story that front of feet is immediately apparent to you but some additional thing has to be done whether it's just scrolling or maybe clicking on a little like show thing to actually see the comments we can make the response we can make this interface extra responsive by saying hey I want to get the story message and author immediately and then like hey in a subsequent part of maybe it's a chunked HTTP response maybe it's a web socket client send us the comments like as you get those or send them in a second chunk and so you can this is particularly crucial on mobile where big payloads and comments often can be a much bigger payload than the original story. Paired size affects the transmission the time it takes to get that data you're serving a lot so by saving the core content the user is going to see happen as quickly as possible we can optimize that experience. Defer is really just kind of the beginning of what we're seeing there suppose instead the experience is kind of like on a mobile thing there's like a list of stories and so you want like the most recent story you're gonna see one and then you'll like scroll to see the other ones so maybe we want to stream the stories and we're still deferring the comments these things compose and all that so this will actually as you get a story boom it'll like send that particular story to you until it's sent all of them or maybe web sockets and we're doing live where as stories are happening or as comments are happening we're gonna be just pushing this data to you over web sockets over some kind of chunked HTTP response all of this is all this is still developing but it's the kind of features that I'm confident we're gonna be able to see on the basis of the tool we've been given and and lastly it's also worth emphasizing how much control the client can exhibit over the how what data they get and how they get that data like this is all the server does not know anything about the client other than this document and this is the kind of stuff we're trying to do so absinthe is a GraphQL server implementation for elixir and it's what brings all of this it lets your elixir servers speak to this spec and so when we set out to be an elixir we had or sorry absinthe we had a bunch of goals I'm gonna chat briefly a little bit about where we are with some of those and where we're working to so this is like another little example of some some coded right with absin as you notice we've misspelled our user thing so schemas are compiled and this actually gives a number of a number of features they compile basically into functions on the schema module this lets us do things like really nice error handling so we can tell you not only that users not a real type and you misspelled it but also the line number and sort of why it is that were why it is that we're telling you this is one of several checks we do at compile time to help both enforce correctness and it just makes for a nicer development experience when you can get sort of problems as early as possible but this the schema compilation also helps us do certain kinds of attached metadata to parts of the schema that let us speed up certain things so this is not actually an example here but a lot of a lot of your GraphQL clients are going to be JavaScript and in JavaScript you tend to have field names that are camel case that's not particularly natural like sir we tend to go with snake case we can at compile time know that like you can specify hey we're gonna be interacting with clients that are using camel case fields and so we'll annotate each of the fields with the camelized version so then when we're doing it runtime we don't have to run macro about camelize on the fields or anything we don't have to do any runtime transformations to grab particular fields we can try to do as much as we can at compile time because GraphQL is a complicated system we don't want to introduce any overhead into your your wildly fast Phoenix performance experience can also help us this is a a chunk of schema that's using some pagination conventions that have developed around one of the Facebook built GraphQL client there's some sort of mechanical translations that have to happen to build some helper helper stuff for that pagination and we can also do again all about a compile time when you don't have to write a bunch of really verbose boilerplate stuff we also don't have to pay a performance penalty so these are just some of the like basic developer ended stuff that we've been trying to do so far and and so what we have coming up real quickly this is we're hoping to get this out in like the next couple days as a release candidate so how do you go from a GraphQL document to the response like what goes on there turns out a whole lot more than we thought when we started the GraphQL JLS implementation has something around 30,000 lines of JavaScript code and that's like us 60 s7 where the stuff to like minimize boilerplate and stuff it is nuts and so when Bruce and I set out to build this originally we just built something that worked and that was in and of itself quite the effort but what what's kind of happened there is that the code that came out of that is a little bit difficult to follow and it's definitely not extensible so what we're trying what we're coming out with is basically an approach to executing that breaks the problem into lots of little phases so you'll notice both of these things are basically trees and so we represent the schema or sorry the query that comes in as a tree of values and then we just walk that through a number of functions that just transform and tag that tree with stuff like hey this should be null or this shouldn't be null but it is and then later on we can kind of grab that value off and return it to users this is because we're really trying to sort of bring this to the community at large and an important part of that is making sure that our code is understandable so that people can actually contribute to it understand it if they find bugs figure out why that kind of thing so things that we're really kind of aiming for in the future we already do compilation on the schema like I talked about but what we what we would like to also do is actually compile a lot of the queries themselves so if you have something that's particularly performance critical you have to remember this is a Facebook technology they know a lot about having serious perform performance pressure and so we're trying to with because we have this the execution model broken into many steps we'd like to be able to execute some of those steps on chunks of a document and then basically like either bake into a module or store an ETS or something all of that work done kind of ahead of time so that when the last bit of actual data comes in you can then like run those remaining steps and we have as little overhead as possible so that's like this is sort of a proposed absent sigil for example maybe you could have in a document we're not really sure we're sort of working on making sure the the building blocks are there to do this and we'll see kind of where it where it leads us as far as the implementation of the sort of API is concerned there's another feature that often comes up is a term projection if you want to see a graph implementation that is really really I think ahead of the curve the scala implementation has served as a great source of inspiration to us and major props to those guys and so the the feature idea here is when we talked about getting a list of events based on our filters graph make sure that there's not extraneous data returned to the user but it be cool if we could extend that only into for example our ecto query like what if we could just select only the fields from Postgres that are asked for from GraphQL or how do we deal with loading associations in an intelligent way right now you're kind of on your own for some of that stuff we don't have a lot of features there and so oftentimes in practice we tend to just load what we people tend to like ask for or we've got a little bit of logic that can look at the the the query itself and try to figure out what needs loaded but it's relatively complicated and so we'd like to do is kind of provide not literally this interface but these ideas where that second argument to the def events is just some information we provide to your function about the GraphQL context and so we'd like to have like an absent ecto library that can build preloads that can build that's supposed to be selections and so when we are getting our events we'll preload exactly the things that are asked for and nothing more and exactly select exactly the things that are asked for and nothing more and you may be wondering for example how do we how can you prevent people from like kind of attacking your database or your service by asking for the moon and half basically and this is another thing that our our our new execution model is going to enable is a query complexity analysis where given a query you can actually have an algorithm that goes through and waits each query by how much work you think it's going to take and then you can have a maximum limit on how much work a given thing can ask for and all this stuff this is the kind of thing that we're hoping will be possible with with our new approach so the future if there's one thing that has really like stood out with Phoenix is that it's given us some really incredible real-time capabilities and right now you can totally whether it's subscriptions are kind of one mechanism GraphQL gives you or this live data thing we're talking about earlier you could send these things over a channel and have some like callbacks in your channel that call Absenthron or whatever but we'd like to make that more first class we'd like to make that a cleaner a cleaner integration beyond that though the real-time extends beyond the web and extends beyond Phoenix and GraphQL is is actually extends beyond the web itself as well there's you know we're using data that come when data comes in we want it published to certain worker processes that maintain state about objects in the real world or maybe you're having it update local UIs or something the we're trying to we want to use gen stage which you're probably hear a little bit more about from judge Jose's talk tomorrow which it gives us a really generic API for streaming data in elixir we want to target that as kind of our primary API so that you can use this whether using Phoenix channels or you just want to have it stream to some dedicated set of processes streaming to and from that is is I think what we're going to target we don't do yet there's a lot of this that we don't have yet but the and I'm not entirely sure we're going to achieve some of this but when I look at the tools that GraphQL elixir has given us and I look at how from those tools we have this really ridiculous set of features that have come out of that I am completely convinced that this kind of future is is definitely within our reach so that's all I got if you have any questions feel free to hit me up I'll be there sometime now I'm quite sure I hope and I'll be around and so thank you we certainly have time for some questions great talk thanks so is it possible to to restrict your queries on time series data as well so in other words I want let's say I want today's data I want all of it I want to defer the last week and then I want to really defer the last three months on sometimes yeah sure so I will I will I will sketch up what that would look like briefly here if I can make this font size larger so basically is that is that sufficiently readable to everyone okay so there's about a zillion things I did not talk about because there's a lot going on so one thing you can do with GraphQL queries is suppose the name of the feet you want to do several in this case we'll just call it data for some first like start at want to start at a time you know one dot week dot ago we're in Ruby now no and so now we want to do this and we'll just call we'll just say we're gonna get the value suppose we want to do like a couple of these in one thing you can provide an alias on a field so this is like last week and then this part is last month maybe or something and so I'm not gonna fill all this stuff out but you would see how you have a start out and an end out there was like a different point in time you have several of these and then you would and so when you get the response back it will have the last week as like that the JSON key and the next week is a JSON key and stuff and you could have different I've lost my cursor but that's okay you have different defer on here directors take arguments so you could have like defer level or something I don't know this this API is still sort of developing but you could sort of have a priority there that's your question cool I just wanted to know if there were versioning considerations like yes so one thing that my coworker Bruce told me about nine times to mention and then I forgot to mention it was that GraphQL is first-class support for deprecation so you can deprecate fields with a reason and so on the pattern that it tends to follow is that you tend to deprecate stuff and then replace it with with some other fields there is not explicit versioning some people have tried to kind of follow a pattern where everything is kind of namespaced under a version so nothing stops you from doing this you know and so people people do this in general the pattern tends to be that you don't change what the existing types and values of fields on instead you just make some new new field and or deprecate the old one and when people are getting the data back they'll see the deprecation notice and it'll have some time span associated with it further questions yeah so in GraphQL when you execute a query and you have different fields you're getting yes you can do them in parallel according to the spec yes have you gotten around to doing that yet no and no small part because of the limitations around our previous execution model we could have tried just basically a like in a map task async part of the reason we didn't want to do that is that we with the beam and concurrency you want to not shoot yourself in the foot because we're passing back relatively large data structures often and so we wanted to try to look at that in more detail maybe leverage some of the concurrency limits the gen stage gives us so that we can not we can sort of have a good balance between do it optimum benefits we get from concurrency and a balance against the the cost of copying data sometimes and and so forth that is a really good point though one of things I really like about GraphQL is it does have a the question of concurrency addressed in the spec where if you're doing a query of just getting data you have to implement it in a way that allows it to that allows it to be concurrent so you know don't be don't be you know updating some counter somewhere and it's gonna screw up your concurrency mutations on the other hand where you're altering data always run run serially and it's I think a good sign that the spec kind of addresses those kinds of questions so you hang going up please stand up until I can give you the mic this is what happens when your your presentation timer resets you don't know how long you took so I've worked in the past with the graffiti mongoose library have you aware with that it's a node library I have written about 10 lines of no JS in my life okay well it's kind of cool so basically it integrates with the model layer so it can automatically generate you some of your queries for you oh cool so you should definitely look at it but is there any plans to kind of like look at Ecto schema definitions and be able to kind of auto generate some of those things instead of doing them the schemas twice yes so one important caveat there is that GraphQL is supposed to be a data model for your API clients which may have a lot to do with your underlying Ecto schema and it may have nothing to do with your Ecto schema or in our case it actually hits some in-memory processes sometimes it it's so with that caveat there you know there's not always this one-to-one correspondence yes we actually already have or certainly had and need to update just a mixed task to say hey give an Ecto schema I'd like to to generate a sort of analogous thing we're probably gonna do that in a sort of mixed task it's kind of a helper tool what we're gonna avoid doing is like a big macro that's like hey this is based off this thing because then you're generating a ton of code you can't see it's hard to modify etc etc so yes more of a general GraphQL question so the whole model works really well if you have a kind of a single data storage underneath like a single database for instance is there a story to run GraphQL against something that is highly distributed like when you basically your data lives in like 10 different data stores somewhere and you have to like put it together so I used Ecto as an example because I as elixir developers that's a relatively common kind of base of experience but actually GraphQL is designed for literally that Facebook used it as a common they wanted a common interface over the dozens of different kinds of data stores that they have underlying and that's part of why at the applicant when it comes to actually getting the data for a function it's calling pure elixir code that can reach out to Ecto it could reach out to in memory processes it could reach out to a bunch of different things crazy or still in a lot of cases where Facebook has had situations where you have two services they both expose a GraphQL API they want a third service that would basically you could ping that and it would route to the correct thing because of introspection that third service could introspect on both of those queries and generate the sort of Union Union schema that would cover all those cases and then route data accordingly so it's it's entirely possible I I'm speaking in generic terms because I've not other than other than sometimes calling Ecto and sometimes calling some in-memory modeling we do I don't have a lot of personal experience doing that but it is certainly the origin story honestly of GraphQL well okay then give Ben a big hand