Build a Fullstack Next.js App, v4

Key-Value Store with Redis

Brian Holt
Databricks
Build a Fullstack Next.js App, v4

Lesson Description

The "Key-Value Store with Redis" Lesson is part of the full, Build a Fullstack Next.js App, v4 course featured in this preview video. Here's what you'd learn in this lesson:

Brian introduces caching and its role in scaling applications, demonstrating how to set up Redis for API calls. He also discusses challenges like cache eviction and the thundering herd problem and how to handle them.

Preview

Transcript from the "Key-Value Store with Redis" Lesson

[00:00:00]
>> Brian Holt: Do you remember how I was ranting earlier about premature optimizations? Let's go do some premature optimizations, as one does. Yeah, I would never do this until I had scaling problems because caching is hard, cache eviction, like caching errors, like if I deploy something and my cache is wrong, then like how long is the cache going to be wrong? There's a bunch of problems with caching.

[00:00:30]
I want to show you how to do it because it is an important part of scaling apps, and this is like a full stack enterprise kind of app thing. You would definitely hit problems where you would need a cache, but I would wait until you specifically say like this API call gets called at like this time of day that has these kind of problems. Therefore, I'm going to cache this result for this long.

[00:00:51]
If you can't answer those kind of questions, you have not hit the correct scaling problem yet or you don't understand your problem enough yet. But YOLO, let's do it. Sounds fun. Okay, as we have so many other things here, we have the DB, we have components. We have all these different things here. So we're going to make inside of our source directory another directory and it is going to be called cache.

[00:01:20]
Okay, and I'm going to create a new file in here. This is going to be called index.ts and we're going to import Redis from @upstash/redis. Constant Redis equals new Redis. URL is process.env.UPSTASH_REDIS_REST_URL and token is going to be process.env.UPSTASH_REDIS_REST_TOKEN and then export default Redis. That's it. It's the whole thing. Let's go grab these.

[00:02:30]
We should be able to get these directly out of our portal. Yeah, right there. Copy that business right there. So I clicked this should copy both of those, go to my .env again, and just blah Upstash. Okay. Now we're going to go to articles.ts. So lib data. Lib data articles. We want to specifically cache get articles. So what we're going to do, we're going to say at the top, import Redis from @/cache and we're just going to say const cached equals await redis.get.

[00:03:50]
This is whatever you call the key. It's like naming a value on a JavaScript object, it's just whatever you call it. If you call it there, you have to call it here. There's kind of a standard, a way of doing things here of using colon to basically separate things. So I'm going to have articles like it's like name spacing, essentially. It's not even essentially, it's literally what it is.

[00:04:18]
So articles here, and then I could have like articles:1234, right? You can imply hierarchy with the colon here. Here I'm just going to ask for all. And then I say if cached, so if it does come back with anything, then all you have to do is say, I'm going to say a console log here. So I'll have like a target. Let's say get articles cache hit. Return cached.

[00:05:03]
If you don't hit that, then I'll just console.log. Thinking face. I think I did bow and arrow is what I did here. We'll do that instead. Whatever emoji strikes your fancy. Get articles cache miss. So let's look just like look at this. We're going to ask Redis like, hey Redis, do you have anything in here like this? And it's going to say yes, I have something in here, here you go.

[00:05:32]
And this will, it'll just return this right away, so this never gets called down here, right? Worst case scenario is it misses, so you hit here, and then it goes and actually queries the database. Now let's talk about one of my favorite scaling problems called the thundering herd, and I learned about this when it happened to me. When I was at Reddit, 2014-ish, something like that, we're running flash sales and I realized like I used to run like the Reddit marketplace, so like we would sell stuff to Reddit users.

[00:06:13]
That one of our cache was like overly stale, so it was not showing new products that were showing up to things and we had a bunch of users coming through like trying to buy stuff from us. I was like, oh cool, like our cache is like not is stale, it's out of date. Evict cache, and all of a sudden these like 100,000 users that were on our site all hit this all at the same time before the cache could repopulate, and all of a sudden everything just got crushed.

[00:06:39]
Our database went down, the site went down, the flash sale like blew up, everything was on fire. That's called the thundering herd because you have like something that's keeping this like herd of users from hitting something, and then you just like remove the barrier and the herd just crushes everything behind it. This would be very prone, what I just wrote here to thundering herd problem, right?

[00:06:59]
If you evicted this at the wrong moment, and you didn't repopulate it quickly enough, and this was like a serious amount of scale behind it, you would hit a thundering herd. Again, it's not really a problem for our use case here, like I don't expect anyone at one given time. I'm just trying to like over the long tail reduce load on the database. I'm not trying to prevent like this like dam of users, like a flash sale like I had.

[00:07:29]
The way that you would fix this and not have thundering herd is you would never evict the cache, you would just override it, right? So rather than me going in there and click the evict cache button, which like when I say evict it's like delete this cache, right? You would just make sure that like rather than evict the cache, you would just go update it, right?

[00:07:49]
And then people would never hit the database. You'd even might even just like not have this. And if like you hit this point, you would just throw an error and say like, this is an error, we should never hit here, there should always be something in the cache. Does that make sense? This is pretty typical though, like look for the cache, if it's not in the cache, go get it from the database, and if you have to go get it from the database, then you'll populate the cache.

[00:08:28]
So now that we have hit this, we need to go populate the cache. So what we're going to do is underneath this, but before we return the response, we're going to say, I want to say redis.set articles:all response and then how often do you think we should refresh this? I don't know, like it's actually kind of a hard problem, caching is a very hard problem.

[00:09:05]
So I hope your first answer is like, well, it just depends, right? How often is this stale? How often is it okay for it to be stale? Is it ever okay for it to be stale? Like this, you're asking like if someone comes to the front page and sees something that is a minute out of date, is that okay? 10 minutes out of date, a day out of date, two weeks out of date, like there's a line here, and it's probably a couple of minutes is what my feeling, right?

[00:09:34]
And you always cache based on feelings. That's what I found in my career. I put 60 seconds here. I'm okay with this cache being like 60 seconds out of date. I'm assuming that it's probably going to get updated, at least this is probably okay to like leave it like this. What we're also going to do is anytime someone writes to the database, we can just go say evict the cache as well, right?

[00:09:57]
So this is providing like some light shielding around our database, but we're still going to hit our database quite a bit, and it's PostgreSQL, it's Neon, it'll scale just fine. This is a simple use case of this, but you're seeing like the simple patterns here. So let's just go try this. Before we do anything else. So where's Wiki Masters here? We got a cache hit, cache hit.

[00:10:52]
But you can see here, it's now pulling us all out of cache. If we go look at Upstash, data browser, you can see. Oh, it's probably expired now. Yeah, so you see a cache miss there, but if we come back over to Upstash again, you can see it's here, and it's here at least for 49 more seconds. Pretty cool, right? And I can always come in here and just say, well, delete it.

[00:11:34]
Right, and then if I came back over here and refreshed, I should get a cache miss, but it'll get repopulated. So just to show you, let's go into app, actions, articles, we're going to go in and say once we've inserted into the database, we can just say redis, which I made this auto import at the top. So import from cache right there. This is update. And I actually don't want to do it on update.

[00:12:16]
I want to do it on create. So I'm going to say redis.del, which is short for delete, articles:all. So now anytime that I come in and create a new article, it'll immediately just evict the cache and it's like, well, I got something new. And so the next person to hit it, which will probably be yourself, right, because it might redirect you back to the homepage or something like that.

[00:12:38]
You'll actually get to see your article there, because it's really frustrating for users to do something and then not immediately see the results of it. They think something's broken, right? And so in our case, we don't want to do that. That's it. So I was going to show you this with Vercel. You definitely don't have to do this, you go to settings or is it integrations?

[00:13:18]
No, you have to be on your project. Don't do that. Wiki Masters settings, integrations. So I have already connected up Upstash here, but you can say configure, new integration. So I want to, well, let me just do this because I think it's more useful if you just see me go through the whole process. Yours is probably going to say something like install. So you'll say like search browse marketplace and you could say in here, I think Upstash will show up in here.

[00:13:55]
You just say install just like this, install. You do not, so you can set up everything through Vercel. So you can set up Neon through Vercel as well. I think you can send Resend, we're about to do Resend as well. I like having the separate accounts in these particular cases. For we'll go with, every time that we launch a new feature on Neon, we have to go back and backport it into Vercel.

[00:14:18]
So there's just always a little bit of lag between when Neon releases something and it makes it into Vercel, and it's just that's how their marketplace works. That's why I like having a separate account. Okay, so I've done that. I select a team. I only have my own. That's a connect account. Okay, that's great. Here I'm going to select FEM Wiki Masters. I'm going to connect that to FEM Wiki Masters.

[00:15:00]
Don't need QStash. I think that's their like queuing project, like event grid kind of thing. We don't need that. And there we go. So now I think if we go into storage, you actually will. I go into FEM Wiki Masters, and they go into storage. Or is it just integrations? Integrations configure. Configure, I thought we already do this new integration. Submit.

[00:15:45]
There we go. I think mine because I wasn't actually installing a new connection, I was trying to do that, so. Now I think if I go into FEM Wiki Masters, integrations, configure. Well, let's see if it actually shows like the value add here. Why does it keep putting me back in the main dashboard? That's so frustrating. Settings, integrations or environmental variables.

[00:16:08]
Yeah, here we go. This is what I was looking for to do. It will now manage all of the environment variables for me, I don't have to manage those anymore, which is great. And I can configure like different ones for production, for preview, for environments, all that kind of different stuff. And it all just works. If I like go into Upstash and I say like delete all of my, or like roll all of my credentials because someone leaked them or something like that, automatically updates Vercel for me.

[00:00:00]
I think Upstash also has some integration here where it can like, its monitoring works a little bit better. I can say like this is being called from here in Vercel, so it's a little bit more connected that way. We'll talk about the Neon one towards the end of the course because Neon does a lot more with like branching and stuff like that, so.

Learn Straight from the Experts Who Shape the Modern Web

  • 250+
    In-depth Courses
  • Industry Leading Experts
  • 24
    Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now