GraphQL was originally not designed as a database language yet it's quickly becoming a popular choice to interact with databases. What if databases natively support GraphQL default? What are the advantages of native GraphQL support? How is a GraphQL query handled behind the scenes in FaunaDB and what database guarantees does such an approach provide?
Native GraphQL, GraphQL as a Database Query Language
Hi everyone, I'm Bricht, I'm super excited today to talk at the graphql Galaxy conference. I'm DataBricht on Twitter, I work for the FANA database and today I'm going to talk about Native graphql or graphql as a database query language.
Now if we talk about Native graphql at FANA, what does it mean? Well, first of all, we have a FANA query language which we call FQL and basically Native graphql 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 two, 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 and title are fields will map on a function. So getList will be a function and that will delegate to the todo 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 one 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, to do.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.## Related [graphql as a database query language](https://youtu.be/PmSVyOo6gC0) - Talk by DataBricht from the graphql Galaxy 2019 conference
Well, why? Your data is no longer live. It's no longer consistent. You can't apply it on everything. You can't batch everything. So you will have still multiple calls. What about caching validation, memory pressure that you have to 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. It is live by default. It is consistent. It requires no extra work and there is no memory constraint problem. It just works out of the box. So you don't have to do this. Solution two, generate one query, which is what FANAS does behind the scenes. But why doesn't everyone do that? If we would look at SQL, for example, and let's say we would select a star from lists where ID is equal to something, then we would go to the to-do calls and do the same and try to concatenate that query. Of course, we'll have to do it for multiple to-dos. So we'll end up with a join. And the problem is if we go deeper like that in a graphql traversal, we might end up with a lot of joins. Now, not only is this super complex to analyze this query and then generate SQL from it and then transform the results back to a graphql format, it might also be inefficient depending on the joins. You might overfetch a lot and then have to throw away things. And then how are we going to paginate this? ID 100 might not be exactly what you're looking for. So the problem here is that what joins solve, which is a join between two tables, is a different problem than what the actual problem is, which is more like a tree traversal problem or a graph-like problem. So joins are maybe the wrong tool for the job. So there is an implementation, a very impressive implementation called JoinMonster, which actually comes from the problem they're trying to solve, a monster join that might be the result of a graphql query. If you look at the work involved, you can see that it's a complex problem to solve. That's question four.
I hope you like that idea.
And if you want to try it out for free at vanna.com.