We're sorry but this page doesn't work properly without JavaScript enabled. Please enable it to continue.
Feedback

Best Practices for GraphQL API Development

00:00

Formal Metadata

Title
Best Practices for GraphQL API Development
Title of Series
Number of Parts
141
Author
Contributors
License
CC Attribution - NonCommercial - ShareAlike 4.0 International:
You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal and non-commercial purpose as long as the work is attributed to the author in the manner specified by the author or licensor and the work or content is shared also in adapted form only under the conditions of this
Identifiers
Publisher
Release Date
Language

Content Metadata

Subject Area
Genre
Abstract
Must-have tools for running GraphQL in production Gear up for a groundbreaking transformation of your GraphQL prowess! Join us for an engaging and informative session as we unveil a set of indispensable tools and practices that will take your GraphQL APIs to new heights in production environments.
114
131
Different (Kate Ryan album)Product (business)Computer animationLecture/Conference
Computer virusFront and back endsOffice suiteBootingHydraulic jumpComputer animationLecture/Conference
Arithmetic meanSoftwareDifferent (Kate Ryan album)Server (computing)Library (computing)ResultantQuery languageCASE <Informatik>Formal languageComputer animation
Information1 (number)Point (geometry)InformationRepresentational state transferComputer animationLecture/Conference
Kolmogorov complexityComplex (psychology)Query languageMiddlewareCoefficientSoftwareNumberRepresentation (politics)Inheritance (object-oriented programming)Object (grammar)Cartesian coordinate systemBefehlsprozessorCASE <Informatik>WeightQuery languageMathematicsBinary multiplierBitCoefficientError messageComplex (psychology)DatabaseRepository (publishing)String (computer science)File viewerPressureComputer animationLecture/Conference
Query languageLevel (video gaming)DatabaseQuery languageGame controllerAuthorizationType theoryServer (computing)Software developerMoment (mathematics)Library (computing)Table (information)Computer animationLecture/Conference
Graph (mathematics)Type theoryTerm (mathematics)AuthorizationGame controllerTraverse (surveying)BlogComputer animationLecture/Conference
AuthorizationQuery languageTorusRollenbasierte ZugriffskontrolleZugriffskontrolleLogicType theoryEndliche ModelltheorieSelf-organizationReading (process)Arithmetic meanMehrplatzsystemQuery languageMultiplication signValidity (statistics)Different (Kate Ryan album)File viewerCartesian coordinate systemNumberMereologyPhysical systemEmbedded systemComputer animation
Query languageSlide rulePoint (geometry)Multiplication signComplex (psychology)Limit (category theory)CASE <Informatik>Computer animationLecture/Conference
Bit rateLogicLimit (category theory)Multiplication signLibrary (computing)Type theoryCore dumpDifferent (Kate Ryan album)Lecture/Conference
Kolmogorov complexityPoint (geometry)Bit rateQuery languageArithmetic meanComputer animation
Query languageType theorySocial classField (computer science)Library (computing)Connected spaceArithmetic meanMultiplication signWeb pageClient (computing)Maxima and minimaQuery languageType theoryElectronic visual displayDemo (music)ResultantElectronic mailing listObject (grammar)Computer animation
Latent heatMultiplication signLatent heatComputer animation
Event horizonDemocratic Action PartyIntegerInternet service providerInternet service providerService-oriented architectureImplementationBitWeb pageExistential quantificationMultiplication signDesign by contractReading (process)MathematicsControl flowMobile WebThumbnailAutomationEvent horizonRevision controlClient (computing)Bit rateLibrary (computing)Error message2 (number)Software testingInterface (computing)Arithmetic meanBoom (sailing)Mobile appType theoryRepresentational state transferEmailBlogRight anglePoint (geometry)Computer animationLecture/Conference
Multiplication signComputer animationLecture/Conference
Type theoryTraverse (surveying)ImplementationResultantValidity (statistics)Error messageInheritance (object-oriented programming)CodeFile viewerEvent horizonQuery languageMultiplication signBitMiddlewareNetwork topologyAreaFehlererkennungPhysical systemUniqueness quantification2 (number)Right angleLecture/ConferenceMeeting/Interview
Computer animation
Transcript: English(auto-generated)
Today we are going to talk about GraphQL. So I just want to see if you know what GraphQL is. Can I see a show of hands? I think you all know, perfect. Have any of you used GraphQL before?
Very few, but that's still great to hear. So this talk is about the tools you might need. When you want to run GraphQL in production. And I'm going to mention why that is a bit different.
And yeah, let's get started. But before I go on, I'd like to talk about myself. Hello. It's me, Arthur. I'm currently working for KrakenTech as a lead backend engineer, and I'm leading the APIs team, which makes these tools.
So these are the tools our team has been doing, and I'd like to present them to you. If you are looking for a new opportunity, or if you'd like to join Kraken, and we have I think offices nearly in ten countries now? Or cities.
Cities and countries. Please, we have a booth outside. And just join and say hi, and we'd love to chat to you. So let's jump into these tools. Why do we need these tools? So GraphQL, about five, six years ago, I started using GraphQL, and back then it
was a bit magic, because just a quick introduction. So unlike REST APIs, when you make a request to a GraphQL API, it's a query language, meaning you just tell the server what you want, and then the server looks at your language,
like SQL, and just gives back to you the results. But this design is perfect for many reasons. Like it lowers the network costs, and it's faster and easier to build, and has tons
of benefits. I'm not going to go over them. That's out of scope. But due to this design, you have to treat things differently. And I'm going to present these as problems, and I'm going to show you the tools we've built in Kraken to address them. Some of these newer libraries over five, six years, and growing community of GraphQL Python
libraries might eventually decide to address these and have these as built-in tools that you could just install and use, but currently that's not the case for some, but I know
some of these tools are already being developed in the new GraphQL library, so please check them out. So let's start with the first problem. Someone requests too much information. So in the REST API, you have an endpoint, and you just hit the endpoint.
That's requesting one thing. But in GraphQL, you can request a thousand things, right? Because no one's really stopping you to say, okay, you have requested too much. How do we solve this problem? And the problem was this was one of the first things I did when I joined the company
was to check the query complexity. And in a simple way, for example, here you see we are requesting a viewer, and let's say this is a GitHub, okay? This was inspired by GitHub, and then you are getting the repositories as nodes, but
then you are asking for the name, and for each of those 50 repositories, you are also displaying the title and body HTML. When you look at this, it's a big query, and we said we want to look at this query
as a string, and we want to be able to extract things out and then kind of find a number, get a number, compute a number about how complex a query is in a simple way. And we also would like to take into account the nesting and the parent children objects,
because then the number of objects you are getting and the pressure maybe you are putting on the network or the database or your application grows. So this was what we did. We created this query complexity tool that, given a query text like this, gives you a number.
For example, for this case, it's 50 repositories, and for each issue, you also get a different number. But this simple case, we have taken it a bit further.
We said why not have different coefficients? Maybe some of the queries are more expensive, maybe they are making network goals, maybe some of the queries, you have to do lots of SQL and number crunching or CPU things. So each of the things that is being requested can have a different weight, so that while
doing the maths, you also put in a coefficient like a multiplier for each of those nodes so that you have a better representation of how complex a query is. So this means, and you can have a middleware saying something like, okay, if this query
is too complex, don't execute it. Stop here and just raise an error without hitting the database or anything like that. So this is like the entry to your API.
Related problem is the depth of a query. So what is the depth of a query? So imagine something like this. You have foo, and as a child, you have bar type, and then as a child, you have the author, and then you are looking for posts of those authors, and then for the posts, you get
the tags, and for the tags, you display something. So you can imagine this would be a big SQL query if these are in different tables or even in different databases. So we want to say, okay, we allow nesting like this, but we don't really want it to
be that nested, and sometimes it's beneficial to have top-level queries for your developers. So we just don't want to give the full control to whoever is asking this.
And sometimes you even have these cyclic things. If your types are not designed in a way, if you want to crash a server, you can do this. I mean, this unfortunately works in some GraphQL things at the moment.
So you can ask for an author, and you can ask for the author's posts, and then for each author, you can ask the posts, and then you can just go on and go on, and this usually crashes a server instantly, so we didn't want to have this. So we created a tool just checking for this or saying, okay, your query is too deep.
Please don't go that deep. This was the second thing. So this is a better known problem. It's about access control. And back in the days when GraphQL was young and just developing, most of the libraries
that you use didn't have this access control built in. And this means that the problem of who has access to what is kind of critical. And for REST or other things, this is easier problem, because you have an endpoint in REST.
If you have access to that, you get that. But what happens when you have this graph of things? So you have blog posts, you have authors, and authors have other things. And then these are nested things. So you can really traverse the types, and you can jump from one type to the other.
And this is a difficult problem to solve in terms of access control. So you have to think about that kind of thing. So what we did was we started very simple. We created some decorators to decorate some mutate or query methods.
And this means it was a very simple one. Basically, this was just checking if the user can, let's say, update their electricity reading. If the user, and this is just the logic itself, meaning this is the tool.
Viewer passes check is the tool. But the logic about that is, let's say, you have to be on the account that you are trying to update, or you could embed other business logic, like has enough time passed between updates and about numbers and validation.
So all of that, but this was one thing we did. Until this wasn't really enough, excuse my voice was too much parting last night. So, and then we, in our system, it's quite complex. So we don't have a single user model, but we have different user models.
And one of the types of users are these organizations. So it's not like an account user, but it's like a third-party organization or third-party application. Think of it as OAuth or something. So we wanted to say, we would like to define permissions
for these types or mutations, and we would like to bundle them in roles so that the roles can be assigned to certain organizations. And once those roles are assigned to certain organizations, those organizations with their API access would be able
to systematically get the data they want. Of course, since these permissions are here, it means they can get, they cannot get everything that all the customer gets, but they get less, basically. Okay. Another problem, this is a well-known problem.
Someone's making too many requests. And the team, we have created two tools to address this issue. And these are unfortunately not built in, but we had to create them. And our inspiration was, again, GitHub for this case.
So you might remember the first slide about determining query complexity. So when we look at the query, we kind of know how complex it is. And we said, okay, for a given hour, we would like to define a limit for a user, maybe let's say 5,000 points per hour.
And each time they make a request and it is successful, we would like to deduct those complexity points from the user's allowance. So this is quite smart and flexible because maybe you need to get a lot of data, but you don't really want
to be limited like in a basic way. You can get all the data, but this was just creating some fair use of the API because then if you are over your quota, if you don't have any points left, you can't do any more queries
and you have to wait some time. This is what we have kind of implemented as a custom tool. But there's also one more thing, and this is, excuse me, the rate limit, this is a Django library actually. You can install it, it's called Django rate limit.
And we kind of took that idea and extended it to create some custom logic. And for example, what this does is it is one of our core mutations where you can obtain an access token to our APIs.
And this means if you fail to log in three times per minute, you are going to get rate limited for some time. So this just opens up ways to create different rate limit types.
You could rate limit by IP, by user, by logic. You can define the limit, but this is really essential. And while this is like looking at the bigger picture of what user allowance has to do, this is a really fine-grained approach,
meaning you can really be specific about this thing and you can really tightly control how the experience is going to be. I'm going to talk about a few more tools. We did not write them, but these are must-haves.
And I think all of the GraphQL libraries include those things, so I highly recommend you use them. And one of the problems is you are asking for something, but the results, let's say a list, has 1,000 items or 10,000 items, and you don't want to display those 10,000 items
because the client who is asking for it can't even show them on a page or, I mean, they can't display them. So the solution is pagination. So in GraphQL, you could do pagination, and all the libraries have tools to do pagination.
We were using Graphene. So this is how you kind of define the connection object. And this means every time someone makes a request, they will be doing the requests in pages.
So they can't, you know, return 1,000 items, but you have to return them in smaller chunks. And the good thing is that you can enforce this, and we really enforce this on our queries, meaning this means you can maximum request 100 items
from a paginated query, and if it's paginated type, meaning if it's something like this, the connection type, you must include the first or the last argument, and I don't really have time to show this as a demo, but you have to say, give me the first 10 items,
and then you can say, give me the next 10 items, or you could say, give me the last 50 items, and then that's how you actually construct your query. This is really a must-have. And just to conclude, how much time do I have? 10 minutes, that's good. So these are not GraphQL-specific tools,
but it's really good to have things when you're running GraphQL, and this applies to many other tools, but I just want to come up with a few things. So in GraphQL, you don't really do versioning. You deprecate things, and then you replace them
with a newer version, so they're both available at the same time, and after some time, you just remove the deprecated version. But the thing is, sometimes you want to do breaking changes, or you want to communicate this with the stakeholders, people who are using your APIs, your customers, or other companies
that systematically consume your APIs. This is a very hard problem, because sometimes, if the API is public, you don't know who is using them. So you have to create kind of tools to reach them out, or they could subscribe to your breaking changes, and then once you say, okay, I'm going to deprecate this
in three months, they would be made aware. And for this, we have created Kraken API announcements, which sends you an email, has an RSS feed that you could put anywhere in Slack or other RSS readers.
It just pops you up, or you even have a blog-like interface, as you see here. The other problem is knowing when something's not right, or like performance issues, and you definitely, definitely need good dashboards,
some event monitoring about what, like the error rates and what's been requested and how they perform, or even alerts that kind of say, oh, something doesn't need, that doesn't look right, can you please check this so that you could be notified
about this from Slack, so these are real must-haves. And the second thing is, you know, this GraphQL looks like magic to some people if they have not used it before, and it's not really common knowledge,
so we try things, we fail, we learn, and then we try again, we fail some more, we learn some more, and then we publish these into conventions, the best practices, for our internal team, of course, and sometimes we share those things in conferences like this, but long story short, these best practices really encourages people
to do things in the tested or best way for that time being, until we come up with other things, so if you are going to do GraphQL, make sure your team, all your team is on the same page about those things.
And I think last two items are linters. Yeah, those best practices are great, but who reads them? Sometimes people don't read them, so if you can automate something, please, please, please, please do automate them using linters, and there are many different linters
out there, you could use flake8, we've started to use fixit recently, and we are so far flaked into rough, meaning, if it's a convention, and if you can automate it, just do it, and the fixit library is even fixing things for you, like black does, when it's not the best practice,
it's a bit harder to write, but it saves tons of times. And I think this is my last point, the pack testing, now this is a contract testing, so this means, as a provider, you create a middleman
between your consumers and yourself, and this means that middleman, the broker in between, can act as a way of making sure the changes on the provider side do not break the consumer or client implementation.
Suppose it's the mobile app, and it's consuming your GraphQL API, or REST API, or any API, really, the consumer writes a contract, like, writes a consumer test, specifying precisely how they use the API. They say, I'm calling this endpoint, I'm expecting this HTTP status,
I'm expecting a buddy with these items, and in this shape, and in this type, whatever, whatever, they write this as a test, we verify the test, we say, okay, thumbs up, this is correct, we can provide you this, and when we verify this, it's a handshake. It means now we have a contract, and it's a pact,
and then we upload that to the broker, so any time any of our team is doing a breaking change, boom, the broker says, you are going to break this client's mobile app, be careful, don't do this, so this is really a must-have. So, this is all I had to say, I hope you enjoyed the talk.
I'm happy to take any questions, and again, excuse my parting voice.
Before we break for lunch, let's show our hunger for questions. We have plenty of time for questions. Hi, thank you for the great talk. I have two questions, actually. Please. Because I'm also struggling sometimes with GraphQL. One of the issues we have is we talk about validation
of permissions on mutations, but the same thing goes for queries, and it could be a bit more complex, because let's say someone has rights to access all of the authors, but for some reason shouldn't have access to posts, and when you have nested query, how do you solve this kind of situation?
So, for a given query, we have a middleware that traverses all the types, and all the children, and all their children's children, like until, imagine like a tree. We traverse it all, and we check on each type where they have the permission or not.
If they don't have the permission, we just return none for those things, and we raise it unauthorized there. But for the things they do have, then we say, okay, this is good, and we give you the result. So, the magic is having a middleware that can traverse the relationships
of the children nodes and the parent nodes, and then just checking if the viewer, if the user has access to those things individually. Okay. By type, by type. Thank you, and second question, it's about actually logging the errors in the API,
because most of the GraphQL implementation tend to return 200, even though there was an error in the API, so it's a bit harder to log it and view it in some like Grafana or Dashboard. How do you do that? It's by design that GraphQL returns 200 for the errors,
and so we raise custom events for errors, and not all errors are the same. Errors are unique in our system, so we have these unique error codes. I haven't told those out of time, really, but we have, each error is unique with that code,
and we kind of log them on a different system, so that we use those events about the errors to display this Dashboard or visualize them. Not like just, we don't depend on HTTP codes, because they don't work, really.
Okay, thank you. No worries. Are there any other questions? If not, we can thank our speaker again.