Hi everyone, I'm Brichts, I'm super excited today to talk at the GraphQL Galaxy conference. I'm Databrichts on Twitter, I work for the Vana database and today I'm going to talk about NativeGraphQL or GraphQL as a database query language.
Now if we talk about Native GraphQL at VANA what does it mean? Well, first of all, we have a VANA query language which we call FQL and basically NativeGraphQL means that a GraphQL query is going to translate into one FQL query. That one-to-one translation has huge advantages, so first of all, you might wonder which advantages we'll look into that, and question 2, why doesn't everyone do this if there are such advantages?
To answer these questions, we actually have to answer other questions like how do GraphQL resolvers work? So let's take a detour. How do GraphQL resolvers work? Well, typically if you have a query like this with getList, toDo, title, every field in here, like getList and toDo's and title are fields, will map on a function. So getList will be a function and that will delegate to the toDo's function, that will delegate again to the title function, for example, to the title attribute. This is a resolver chain, which is a chain of functions, but it's actually more of a resolver tree of function calls.
Because here there's one function that calls n functions. And if we turn this around, we get n plus 1 and it's basically a problem. And this is actually called the n plus one problem. That's why I turned it around. And when is this a problem? Well, basically, if you're going to call the database for each of these resolvers, because then you get n plus one database calls, which is not efficient. So question four, how can we solve the n plus one problem? Well, there are multiple solutions. Solution one is batching or n in-memory caching. So in that approach, we're going to hook into these functions, for example, todo.titles, and just wait until all the todo.titles are called and then combine these. So instead of going to do n calls for these todo.titles, we're going to do one call. So in total, two calls. That's batching and that's often combined with caching. So if a similar call comes in, then instead of going to the database, we can go to an in-memory cache, so we don't hit the database at all.
A very popular implementation is Facebook's data loader, which you can just plug in on top of your resolvers and it will handle it for you. However, there's a problem with this solution as well. It should in fact be a last resort. Well, why? Your data is no longer live. It's no longer consistent. You can't apply it on everything. You can't patch everything. So you will have still multiple calls. What about caching validation, memory pressure that you have to do deal with suddenly. So it introduces complexity. So the first question, which advantages that FANAS approach provides? Well, it doesn't deal with these problems because it doesn't have these problems.
Comments