 My name is Michael Cullum, that's my Twitter handle. I'm gonna be up here for the next hour so if you want to tweet feedback or abuse at me, whatever goes I'm completely defenseless. So go for it. I'll be in the corner of a bunch of my slides as well. I work for a company called Samnose. Samnose we do internet measurement data. We do deal with huge amounts of data. We do cool things with it, data intelligence, machine learning, buzzword, buzzword, buzzword. If any of you are looking for a job, then we are hiring, so come and chat to me afterwards. I have just joined the Symphony Corps team as a security lead. I am also on the core committee of the PHP FIG, I used to be a FIG secretary until quite recently, and I am also on the management team of PHP BB, so if you are interested in any of these projects come and chat with me afterwards. You are not here to listen to me talk about myself, no matter how much I might like that. You're here to learn about graphs, right? And I don't kind of mean this kind of graph, although this is a cool graph. Graphs are cool. They show us interesting things. We're here to learn about this kind of graph. So throughout this talk, I'm actually going to use GitHub as an example. It's something that we're all quite familiar with. We'll talk about users, we'll talk about repositories. But if we start to think about this as a graph, we have you as a central user. And then so we want to expand out. We want to look at the organisations you belong to. So I belong to SAM knows and symphony, for example. Now, inside that organisation, symphony, we've got a whole bunch of other users. That might be Fabio and it might be Nicholas. It might be other core contributors. I also have a SAM knows organisation, for example. And that contains a bunch of repositories. So some of those are private, some of those are public. And then we have a whole load of commits. Now, each one of these is an object. Now, object-oriented programming, I'm not going to go into the depths of. But you can kind of begin to represent this in the graph. And when you use something like GraphQL, the relationships are first-class citizens and how they all relate to each other. So first of all, I'm just going to talk very briefly about REST APIs. Who's used REST APIs quite extensively? OK, basically the entire room. Wonderful. So, with your sound of REST API, you've got a number of endpoints. You've got GETs, you've got posts, and hopefully a whole bunch of other HTTP verbs that you're all using correctly, right? So if you want to get content, and by the way, by get, I don't mean post content. And I want to have a look at a specific repository. I do get repose ID, and it would return the correct status code because you're all using the right status codes as well, right? Yeah, OK. That's the correct answer. It's the OK answer. Returns to 200 OK. Might get some organisations. We might get a specific organisation. But then here, what we start to do is we start to say, actually, I want to look at the repositories for that organisation. And if you think back to that graph that I was showing you earlier, that's sort of like a child in a REST context. Now, always assuming children actually can kind of confuse sort of the way of thinking about it. And so if you think about them as connections, then you can traverse the graph in any way that you choose. And REST isn't, this is one of the things that REST isn't quite so great at. And then finally, down the bottom, I've got a post org. So creating an organisation. And again, 201, because you're all using the right response codes. A REST API might look a little bit like this. This is kind of fake. And it's also not a great REST API. It's just something I grabbed off the internet. So you'll notice in here that there are lots of links. That was why I grabbed this example. There's lots of links in it. We've got a link to itself. We've got a limit. So a bunch of stuff to do with pagination. And then we've got sort of relationships. And we say, call this other link, this other URL, and then we'll send you through. And that's a REST API. A little bit like a human can browse the internet. You go on to a search engine, you click on a thing, you click on another thing, you click on another thing. It's very rare actually now for you to type in a complete URL to a specific page on a website. When was the last time you did that? Probably a week ago or when you were testing something. But the common user doesn't type a full URL. Now, that's a good REST API if you can follow all the links. But not all of them have that. You can have links in your REST API. It's not really a REST API. GraphQL. So moving on from REST. We'll come back to sort of the differences later. So what is GraphQL? GraphQL is two things. It's a query language for your API. And it's also a server-side runtime for executing queries using a type system you define. What? What does that mean? So essentially there are two different portions to it. You have the actual language that you query with. It's a query language, just like SQL is, for example, when you're querying on a database. And then it's the other side. It's the actual system of managing types. So in our GitHub example, we have users. We have repositories. We have commits. We have more users. And we have a whole bunch of other different types of entity. So let's have a look at starting to query this, right? This is something in GraphQL. This is a request. And what I'm saying is on the me object, I want to get the property name. I want to get my name. It is just as simple. This is the most bare-bones sort of thing you can do. Getting a property off of an object. And this is what it returns. It returns my name, Michael Cullum. And it returns it in exactly the same format that I requested it in. And it only returns me the fields that I specifically asked for. So again, we've got me here, which is the object. And then inside of that, we've got the property name, which has the value Michael Cullum. So it's given me that data. It's given me the name of the me object. Now I can add others. I can add company in here. Because let's say I want to know what my company is. I run that. And again, I get that extra property back. I find out what that property value is. And that property value is Sam Notes. And again, you'll see that company, the exact words I've used here is exactly the same. It's the response will always mirror the request unless you ask it specifically not to, which I'll go into later. Now this is great for scalar values. But I was talking all about graphs and stuff like that earlier, which means that we're going to have to nest objects at some point, right? So let's nest an object. Now I'm talking about GitHub. So let's have a look at some repositories. So I want to get the name of a couple of repositories. So I specify an object here, repos, which is a property, but it's not a scalar property. It's a list. So therefore I say for each of these repos, I want to get the name. So that's exactly what I have. I have repos and then I have a list of repos. There might be, there would be more on there. And then I just get the name of the repo, which is that property. And again, it's an exactly the same format. So I said I'm going to use GitHub as an example quite a lot throughout this talk. So I'm also going to use the, so there's a tool called graph IQL, which is interactive essentially. It allows you to customize your requests in one side. It will do auto completion, et cetera for you. And then it will tell you the results. So let's have a look at some stuff to do with. Right. Can you see that at the back? Oh, that's a bit much. Can you see that at the back? Yep. Cool. So here what I'm doing, pretend that this word query doesn't exist. So here we are. I'm looking at a viewer object. Viewer in GitHub's context kind of means me, the person who is viewing the API I've signed in as myself. This is actually touching on GitHub's production data. I'm just going to have to try very hard in this live demo not to accidentally show you any private repos. So login is the property on here that essentially gives you my username. My username is Michael Cullen. So that's really simple, right? Now we can do something a bit. We can look at other things, other types of object. So on the GitHub API, one of the things it lets you get is a series of codes of conduct. So a code of conduct is an object and it has a name field. So when I was saying about all the auto-competition, this is what I mean. The type which is really useful because my memory isn't that great. It's also why I feel brave enough to do a live demo. So here I can just see it's saying that there are two code of conduct objects that it's finding. And in each of these code of conduct objects I'm getting the name property. Now I can add some more. I can get a description, I think. No, I can't. I can get the body. I can get... I can get a URL. So there we go. So now I'm actually getting the full body of all of these codes of conduct. Now that's great, but realistically, I don't actually want to get the full body of every single code of conduct. So let's say I just want to look at one. So one of the fields that I grabbed here was key. Now the reason... No, I didn't grab key. So I can see here contributor covenant. That's a key. I'll show you exactly how this works in a moment. But essentially what I want to do is I want to only look at one. Help if I didn't lock my screen. And there we go. And I can just look at one. So I can just look at one as well. And that really depends on the kind of object that I'm querying, whether or not I'm looking at an array or whether or not I'm looking at a single object. So let's come back here. So what you just saw me do is I was passing in an argument. So essentially what this actually is is a function if you consider that in PHP terminology. So I'm passing in an argument and all arguments are named. This is not something we really have in PHP. You can't say which arguments you're giving. You can only pass in all of the arguments or just the required ones. So I'm saying login. So that's the variable name. That's the key. And then I'm saying that the value of that equals my column. And then I want to look at the name for that. And then I get back exactly the same thing that we were looking at earlier. This means I can look at all of the users. I can say I actually just care about this one. Because I generally don't care about. I don't want to get every single user on GitHub. I want to get this one user. And I want to specify which user. So I can also use arguments on scalar properties though. Now GitHub, I couldn't find examples of where they do this. But essentially what you could do is say I want name and height. Now, who prefers metric? Who prefers feet? One guy. It's fine. Who measures the height in feet though? Exactly, so most of you. You're not alone. So we can specify the specific unit that we want. So we can say I want my height in foot because whilst I might normally default to metric I prefer metric. I prefer my height in feet. So it would then come up with Michael and 6 foot 4. And essentially what I can do is I can just use that for manipulation of a scalar field. So arguments can kind of go wherever which is an odd concept that we might not be used to. So something I've talked about a lot is that the request and the response match each other. Now, if they always match each other like this, we've got me, a company, and then again here we've got user, name, repose. Again all the structure matches. What happens when I want to get more than one user? Because here I've got user and then I've got myself. Like I'm coming up. But let's say I want to get the data on two users. So I want to get the data on the two most common, the two most popular users on GitHub. Or a highest number of contributions. Now that's Fabian and Andrew. I don't know who this Andrew guy is but Fabian, I expect most of you do know. We use something called aliases. So aliases allow us to actually change the response and use different keys. If I had two users it would throw an error. You saw what an error looked like earlier, accidentally. I was going to show it to you properly later but you've already seen it. So what I can say is I want this object to be called Andrew and I want this one to be called Fabian and what I do is get me a user and pass in this argument and that looks like this. So we've got Fabian here. Fabian, Andrew, Andrew and then we're still throwing through that name because the name is the property that we're getting. Now that's great when you're only looking at one field but let's say that you want to have multiple different fields in there. You want to have name, email, company. Now as a developer this makes me hurt. This makes me want to cry because I'm repeating the same thing, right? Which we all know is bad practice. But GraphQL can handle this for us using something called fragments. So what we do is we say fragment user details on user. So what we're saying is I want to create a fragment. The name of that fragment is user details and we want to create it on a user type. So I haven't really talked too much about types. I'll go into that a bit more depth later but essentially what we're doing is we're looking at a user type here and then what I do is I include user details and then it essentially repeats this, the name, email, company in both Michael and Fabian on that. So if I jump back across to get help I'll never play with this. So let's go with so essentially what I'm doing here is I'm just duplicating what I was kind of just talking about. So then we've got that behaviour that I was saying and you can see the aliases working. So we've got Fabian here, we've got Michael and Fabian and Michael. Can you see at the bottom of the screen at the back? Does it cut off like sort of there with heads or can you see the whole thing? Oh, you've got screens back there, fantastic. Okay, so now I want to add a couple of extra fields. So let's add email, please don't spam me. Oh, no, that's not what I wanted. And let's grab company as well. This uses a funky editor just like all of GitHub's stuff and therefore it tries to do there we go. So I can run that and I've got those extra fields. Now I'll extract this out into a fragment and I'm not going to try retyping it because it won't let me. Now the fragments sits outside of the query that we're doing here. And then I just paste the exact fields in here almost as if it is actually in here itself. Now what if I actually just did a name here and I ran this, it would actually error. If you define a fragment and don't use it, it will error at you. So you can't just simply load every single one of your fragments or transformers I suppose as you could kind of liken them to. You can't just load every single one on every single query. You have to only load the ones that you need. So then I use the ellipse operator to say essentially expand user details here. And then we'll see that that's exactly the same response. This makes life so much easier in terms of instead of having to duplicate things 100 times you can just specify exactly what you need. So we've looked a lot at properties and that kind of thing. Let's start to have a look at operations because we want to do things a little bit more dynamically. Now when we're having a look at all of the previous ones that we've been doing I've just omitted that query keyword. The query keyword is unnecessary but recommended. So all of the previous examples that you've seen just add query at the beginning and you'll be following best practices. Now just like in PHP we can have anonymous functions or particularly in JavaScript, JavaScript does this a lot. It's a lot better to name them. It makes debugging easier to find things particularly when you get one of those errors and you've got a long query. So what you can do is you can also name your functions or your operations. So here I want to get user and company. Now the advantage of this is that you can start to pass in variables that aren't part of your specific GraphQL request body. So it's not part of your query. Now why might you want to do this? Why can't I just like insert it into the query as I build it? If you try to do string manipulation to generate your GraphQL query then you're not going to enjoy your life. It's going to be an absolute pain in the arse. It's going to be horrible to unit test. It's going to be horrible to develop on how many people still spend a lot of time using string manipulating queries together instead of using some kind of query builder. It's a similar kind of situation. So what you want to do is you want to say hi I'm just going to pass in this variable and you can specify types. So I'm going to talk a lot more about types but for here I'm just going to say this is a string. We all know what a string is. This exclamation point, what this does is it says that it's required. An exclamation point means that an argument is required. It will just simply error if it's null. If I excluded this then it would mean that null is passable. The way that GraphQL handles null is that there is one null. Everything is that same null. It's not like each individual type has its own null version. So it's not like the null of an integer would be zero. It's just null. So I grab the login here. I say I want a string and then I say I want the user for this particular login and I want to the name. I want company and I want isHirable. Then separately I give it another body of text which is the variables. So for example let's say this was a call request. I might say here is the body which is essentially the query and here are the variables. They are two completely separate things that you send in your request. Now we can do more things with this as well. We can do if statements. So let's say that I only want to be able to have this method and this operation but I want to use it for two things. It's not exactly a best practice in this example but it's simple enough that it kind of makes sense. So what I say is isHirable. I've actually missed out the argument here for Hyrable. That's my mistake. It should be a Boolean in there. And then it's exactly the same name company isHirable but then I have this particular thing here. Now what that says is only include it if Hyrable is true. This should be a Boolean. Now you can also have the opposite of this and you can say if it's not that essentially. So let's have another quick look at that. So let's grab I only want to look at one. I'll just get rid of this fragment. Let's have a look at it. It's a bit simpler. Now I've kind of hidden this down here query variables. So this is where in the UI it allows me to insert those variables. So I want to grab login. And here as I said I'm inserting the query text just to make it so it works and I want to get company of user. So if I run this it will fail. And the reason being is because I've said that this login here is required and that's what that exclamation point is for. I'm just going to get rid of all that comment text. So yeah so here we can see the string I was provided with an invalid value. Now what I can do down here is that's actually if I go down here I can specify what that login variable should be. So it's all too complete for me. So I can say that this one I want Fabian I can complete that run this and essentially it just auto fills that data. Kind of like code right? Kind of like a query language. Now if I decide that I want to add another one on here so I can add isHirable include if and then I can specify another thing up here. And then I can specify you see this code is like nice but not. There we go. So now because I've passed in true it will tell me that Fabian isHirable apparently. Great. However if I put false then will not like me very much. There we go. And it will then hide that field. So you can use one particular thing of query language send it multiple times and just customize the variables which can help you when you're actually crafting these queries it can make your life a lot easier. So I've talked a lot about fetching data. Now fetching data GraphQL is very very good at fetching data. I prefer it for fetching data because using it to write data feels a bit odd particularly thing as you use a get all the time. All of GraphQL is on a single endpoint. You send it your query you send it your variables it returns a response to you. It's slash GraphQL normally is kind of the standard and it's a get. But you can modify data. Now let's have a look at how we do that. So what we do is we first of all and this isn't actually strictly required but it's good practice to do it. Instead of saying query I say it's a mutation. It's a different type of operation that I'm doing, I'm doing a mutation, I'm changing something. Then what I do is I specify what this operation is called. Now again this is completely unnecessary. It's simply useful to have it there for debugging purposes. I specify the user and then I specify the input repo input. Now I'll have a look at that and on the next slide. Then what I do is I run this operation essentially because all of these are operations. When I'm talking about user and grabbing that what I'm actually doing is I'm running an operation to get that user it then returns to me an object and that's what I'm manipulating. So I'm saying create repo for this user and this repo and it will automatically and then it will persist that and then it will return to me what it's created in the format that I've asked it to. Which is name and description, not name and repo. Sorry about that. Now the way that I define an input format is that you say for your in your schema, which we'll come onto in a moment, we say input we say repo input and then you can specify all of your different fields, you can say their types, you can say if they're nullable. You can even specify that they be another type. So for example I could say repo name description and then I could have organisation and I specify that that be of the type organisation and this allows you to create an entire object when putting it in there. So schemas, how does this work on the other side? So that was all about how we can query GraphQL but how do we actually define the schema of our own GraphQL and the thing is is that even if you're only querying a GraphQL ever it's still very useful to understand how this type system works and the type system primarily belongs on the server but using tools like GraphQL allows you to validate essentially all your queries before you actually ever send them which you can't do in languages like PHP in quite the same way. Unless you use strict types, use strict types. So I'm going to create a type here I'm going to create a conference talk and I specify the different properties on this I'm just using an arbitrary syntax on here but essentially you would define this in your code. So first of all I'm going to have a title which is a string, it's not nullable I'm going to have a speaker also not nullable you can't have a talk without a speaker that would be odd. It's going to be in a track now you can see here is that I've defined a custom type here called track I'll show you what that looks like in a minute. Now I've also and I've got ratings and what I'm using is I'm using this list syntax so that allows me to essentially have an array of different ratings so by this I'm meaning kind of joined in kind of that kind of thing. Now you'll notice I've got an exclamation mark on the inside here what that means is I can't give it a null review so I couldn't I would have like if I had an array and I had two reviews in it and one element that was null it wouldn't allow that null element however there isn't an exclamation mark after the list which means that having no reviews is absolutely fine it just prevents a review from being null it doesn't prevent the list from being null if I wanted to say that there must be reviews on this talk remember join.in there must be then add an exclamation mark here and that would essentially require that and you can use these lists and you can nest them etc etc so at the root of all the schema you have something called query so we were talking about query earlier and that thing that I was talking about adding at the beginning mutation essentially what this does is it defines the highest level of functions that you're kind of running the things that you're doing so I'm saying hi I want to look at this talk I want to look at the talk ID I want to look at the speaker I want to look at this review so that's where you're defining all of those upper level operations to go and get like a specific one or to get a series of them I won't cover pagination in much detail in this talk I might bring up in a get hard demo just to show you if we've got time so what I'm doing here is I'm saying talk I want to throw in the argument ID and it's of the type ID so ID is a special type in GraphQL and I want to return a conference talk if it's a review or return a review if it's a speaker or return a speaker object and these are special objects and types that I've defined almost like a class now it comes with a series of inbuilt types those are string, integer, float, boolean and ID ID it will default to if you're sort of doing a look up and you haven't specified exactly what field it is now you can also have your custom types which should look a bit like this conference talk here this is a custom type so you would add this onto the series the others and you can also have enums most of you that's fantastic Derek we should definitely get this in PHP core sorry seriously though so enums are fantastic they allow us to have a series of different values and only one of these values can be specified so at this conference we have three tracks we have the redshift track I don't actually know how to pronounce this which is awkward because it's a track let's begin Merkai Macari Macari track and the byte mark track and that means that when I'm specifying here the track it means it has to be one of those three values I can't specify anything else it's almost like having a an array on a string for those of you that I'm not using but better, much better because it's a type right so the final thing on this before I go into how to do this in PHP is introspection and I'm just going to jump straight into GitHub and show you this so with a REST API what you commonly need to do is you need to define it in a format like swagger you need to put it on an awful tool like apiary in order to be able to document it or that kind of thing now with GraphQL you can actually ask the API to give you its documentation itself because the schema documents the API you can see all the fields you can see the types of those fields you can bless you you can see the description of all the fields and you can actually just ask GraphQL to give that to you so what I'm going to do is I'm going to use one of these special types so they have a whole bunch of inbuilt types that are special that I'm not going to talk about but one of these is schema and what schema will do bless you that was two in perfect harmony so from schema I can get an array of types so I'm actually just using plain old GraphQL here I'm looking at the types and the reason it's erroring at me is because that's actually an array and then under the types I can say I want the name of the type I want the fields of the type I want the kind of the type and then under fields again this is another array so you're starting to see like how we can nest things here and all I'm doing is query and GraphQL itself so again I can say name description I can see if it's deprecated I'll talk about deprecations in a moment and I can get also its type of the field so this will be huge by the way so what we see here is it's showing me all of the different types that it can give you so under query so that top level that we're looking at we can see code of conduct we can see codes of conduct which is what we were looking at earlier we can see the plural and the singular there if I actually ask for arguments over here it will tell me that under code of conduct which is the idea of the code of conduct or the key I can see licences if I scroll down a bit more I can see organisations that's something we're all familiar with I can see users and down here somewhere will be repositories as well so essentially what this is doing is it's telling me things like the description, the currently authenticated user is the field deprecated yes or no and I can see the type now if I use something called kind of then it will kind of show me the type okay that yeah fair enough worth a try right we can also get the name of a type which will often return as null it's just kind of a quack of graphql in terms of when you're looking at objects versus scalar types as soon as you get down to scalar types these fields will like say string etc I can look at all the different I can actually look at graphql itself and I don't need to document my API right now with deprecations it's really cool the reason that deprecations are calling graphql is because what you can do on a field is you can just specify a deprecation reason as one of the properties of a field and what it will then say to you is it will give you when you're querying this it will say is deprecated true it does that magically for you and it will then also give you a deprecated reason and this allows you to deprecate parts of your API in ways that you can't really do in a REST API because you can't query it about itself really so server side this is probably the most popular library for graphql in PHP it will essentially give you all of the bootstrapping you need it's the dependency of most common graphql or other graphql libraries that you'll see now this runs on a single endpoint file I'm not going to show it to you because it's boring honestly essentially what it does it will grab some input it will register all of your object types so like query and that kind of thing and then it allows you to just execute that it will return a response to you now when we are defining a type what does that look like so I mentioned that we want to always have something called query at the top level I'm kind of ignoring that for now so I just want to define a user type I give it a description I say it's our blog visitor I specify some fields I specify first name I have a description on each of those fields I have the type of those fields I'm essentially doing a check to make sure it's a string I've also got an email field which is also a string and I don't bother to specify other fields like the description so I just literally say the type that's a shorthand syntax there and then I've got this function here called resolve now what this allows me to do is for this very specific type I can choose what I want it to be able to return to me how I want it to get that result do I want it to run a query on some kind of scale of value do I want it to look up from like a map array now this is great when on like a smaller scale but you don't want to have to do that for every single one of your entities so what you can use is you can use a default field resolver and you can say hey if it's on take this type pass it into like this particular type of object and then run this through my ORM for example if you're using an ORM and it can then resolve all the fields for you and do that magically essentially without you having to specify what would end up being quite a lot of complex logic every single time now that's great but if you want to do all this automatically you can use API platform API platform is great I really like it for this kind of thing when you want to just for rapid application development if you can just spin it up you define your entities in something like doctor in ORM thing for it the only step you have to do is requiring that other GraphQL library and it will automatically enable itself it's really cool I will very quickly show you this because I'm beginning to run out of time essentially what I've got on here is I've just got an example of that GraphQL script you can't see that at the back no it's not what I wanted so here I'm specifying a field I'm under query Michael's name I'm specifying a type and I want it to always resolve the string true then I've got all of this bootstrapping which basically says like do GraphQL stuff and when I execute this then it returns adjacent blob which you can't see down here which just says the data Michael's name foo so that's like a working GraphQL on my laptop like in what like 40 lines of code so rest versus GraphQL now Phil put this really well and he did a blog article when GraphQL came out because everyone was like hey GraphQL this thing is amazing I'm going to replace all the rest of the APIs I've got with it now then that caused the backlash of GraphQL is rubbish don't use it for everything and then you ended up with kind of like this this conflict rest and GraphQL are totally different they're completely different they do different things, they do it in a different way GraphQL isn't a magic bullet nor is it better it doesn't solve all of your problems it's not a replacement for rest it's an alternative to rest you can use both of them at the same time some companies do GraphQL is great for if you're working very closely with your mobile developers for example and you just want to give them access to everything you don't want to have any information visibility it's really great if you use it right if you use it for the right things but don't just think oh hey I'm just going to jump over and use GraphQL because it's better than rest it's not better than rest it's an alternative to rest rest is very built on HTTP it has no specification it has no set of tools whereas GraphQL is very specific it's a query language it has a specification, it has these tools available to you I can jump on github sing and I can run queries and it can autocomplete it with complete rubbish like why would you not want that but it can also optimise for flexibility and performance you are always specifying the fields you want you don't have to have this mega-include at the end of your rest API link versioning is great versioning your APIs is bad in general right if you've got v1, v2, v3 please stop a much better way to version your APIs is to deprecate fields and very simply just come up with a new name for the endpoint so for example you might change from users to people or something like that if you really need to make a breaking change but it's much better to just not make a breaking change and with GraphQL because you're always specifying the exact fields that you want it's very easy to know exactly who is using which fields and you can reach out to them and say hey you're using this deprecated field and you have been for like two years please stop, we're going to get rid of it next month and you can automate that process you can automate informing your users that they're using a deprecated part of your API that's cool deprecations are much much better and it doesn't have any kind of version you can't do v1 slash GraphQL what are the issues with GraphQL I've kind of talked to someone already caching it's all on one endpoint it's all on slash GraphQL you can't use HTTP, varnish and that kind of thing in quite the same way also because lots of people are going to be requesting different fields it makes caching a complete nightmare because instead of having one endpoint that everyone is always hitting they're always requesting a completely different version of even requesting that particular resource so basically the answer to caching is be very good at it at lower levels your authentication, your caching etc should all be at levels below GraphQL it should be just above your persistence layer in your business logic layer essentially use Redis basically don't rely on HTTP caching it in quite the same way but you do have the performance benefit of the fact that you're only giving what you need and finally information hiding the whole point of GraphQL is that you don't hide information you don't give them exact access to whatever they want front-end developers love GraphQL because it means that they can just develop without having to constantly ask the back-end team for extra changes to be made it can help speed up development of your back-end team because suddenly you're no longer having to constantly respond to the front-end team and you haven't got that dependency in quite the same way you just give them the API and they can do all the stuff but if you want to do information hiding that's not really what it's designed for I think that's all I've got time for if not I can show you a couple of more quick demos yeah, okay so I can jump over on to here what should I show you so let's have a look at some errors very quickly oh yeah that works so when you're looking at errors it will give you all of the details you need so for example it will tell you exactly where your error is if I had a function name up here it would tell me the exact function that was erroring and it gives you essentially an error just like a Jason Wood