I have no idea how we did that but we did not have any security leaks, right? We didn't have any security policy or something but I think actually, kind of the way how GraphQL works where each individual resolver tells you which data to get from where and we just put a little access control snippet in every single resolver and that meant that nobody could access data that they should.
Anyways, so we were using GraphQL and we were very happy with it. And in my head, after like a month of trying to fix our server database problems, I was like, okay, we have to find a way to reduce our traffic. We have to find a way, without having less users, right, we still want more users but we want less traffic. How can we make that happen? And of course the answer to that is caching. And in my head, I was like, okay, wait, hold on, we've got this public forum thing, right, like we've got a public forum, lots of people access it without being authenticated and just read the stuff, that's like the ideal use case for caching, right. I just want to put a cache thing in front of my GraphQL API, just cache all the queries and hopefully that would reduce our traffic to a level where we wouldn't crash.
As I kept thinking about this, I was like, why can't I just run a GraphQL client at the edge, right, that's really the question I was asking myself because if you've ever used a GraphQL client or heard of one like Apollo or Urql, that's exactly what they do. GraphQL clients make for such a great user experience because they, in the browser, they run a GraphQL cache and they cache all the queries that they see and update them very smartly, on actions, and do a bunch of really smart stuff and that makes for the really great user experience. So in my head I was like, okay, GraphQL clients do this in the browser, why can't I just do this on the server? I just want the exact same thing, I just want to take Apollo client and deploy it on the server, right? Why can't that work? And then, even a step further, if I'm already caching, why can't I cache stuff close to my users at the edge, right? Sunil just talked about CloudFlare and there are 250 cities worldwide, why can't I just put a cache into every single one of those servers and then not only will it save us a bunch of traffic, but it'll also make the experience so much faster for all of our users worldwide. Why can't I just do that?
And so I started looking into this and I started reading about how actually GraphQL clients cache, and that's what I want to talk about a little bit today. If you look at a standard GraphQL query like this one, I made this example up, right, but this GraphQL query fetches a blog post based on a certain slug and it fetches its ID, title and of the author, it also fetches its ID, name and avatar. And really the one thing, the one key piece that makes GraphQL caching possible is the underscore, underscore type name metafield because you can add that automatically to any GraphQL query. And when you add that, the GraphQL query ends up looking like this, right? You have this magic underscore, underscore type name field in your GraphQL query. Now, you don't have to define this. Every single GraphQL API supports this because it is in the specification. Every single object type in your GraphQL API has to have an underscore, underscore type name field. What does that field do? Well, if we ran this query and we get back the data, what we would get back looks a little bit like this. It's the post data and then there's also these two underscore, underscore type name fields that tell us that the post is of the type POST, duh, and the author is of the type USER. OK, makes sense, right? We have a POST and a USER. Why is that type name field so interesting? What does that even tell us? Well, we can now look at this and go oh, OK, I can take this entire data, this entire response, put it into the cache, and I know that this response contains the POST with the ID 5 and the USER with the ID 1. OK? So we know that this response that we've just put into our cache contains the POST with the ID 5 and the USER with the ID 1. So what? Why is that? Why do we need to tag our cached responses with anything? Well, here's the other thing that's cool about GraphQL. It differentiates between queries and mutations. And so if we have a mutation like an EDIT POST mutation, where we say, OK, we want to change the title of this blog post, again, we can add the __type name magic field to this mutation. And we can say, OK, from the EDIT POST mutation, just let me know which type do I get back. Now, we as humans, of course, we know that EDIT POST probably, hopefully, returns a POST. So it would be kind of weird if that returned a user. That wouldn't make any sense. But the API tells us that as well.
Comments