← Back to blogYouTube Video

Published September 20, 2025

Building a Redis clone in Go - Part 8 (DBSIZE and FLUSHDB)

Part 8 of 21 in Building a Redis Clone in Go

Can't play the video or having issues? Here's the direct link.

Summary

I implement the DBSIZE and FLUSHDB commands in my Go Redis clone, and I show why the obvious way to flush a database is the wrong one. For DBSIZE I take a read lock and return the length of the store map, while FLUSHDB takes a write lock. My main point is that looping over every key and calling delete gets the job done but scales terribly once you have tens of thousands or millions of keys, so instead I just assign the store a brand-new empty map, which wipes the old one in one step. I test both commands against a store loaded from the AOF file: DBSIZE returns 4, FLUSHDB returns OK, and DBSIZE then returns 0.

Key takeaways

  • Flush a database by replacing the map with a fresh empty one, not by looping over keys and deleting them one by one — the loop is O(n) and falls apart at millions of keys.
  • Lock for reading when a command only reads state like DBSIZE; lock for writing when it mutates state like FLUSHDB.
  • DBSIZE is just the length of the underlying store map — no extra bookkeeping needed.
  • Test against a store rehydrated from the AOF file so you know the commands work on real persisted data, not just an empty database.

Description

Source Code: https://github.com/hassanaziz0012/go-redis-video

Transcript

Hey guys, welcome back to this Go Redis Clone series. We're gonna continue building this Redis database clone in Go. I believe this is part 8 of this series. And in this video, we're going to implement two new commands: the FLUSHDB command, which is going to destroy the entire database, delete all the keys, right? And the DBSIZE command, which is going to return the size of the database, which is just the, you know, the length of the map in our database, right? So both of these are super simple commands to implement. So this is going to be a very short and quick video. So let's just go over to the handlers file over here, and up here in the handlers list, let's declare both of these commands. Let's say FLUSHDB, and what was it? DBSIZE. There we go. And then let's declare both of these functions down here, and obviously, they will take the same parameters and arguments that the other handlers take, right? So that's the FLUSHDB command, and this will be the DBSIZE command. There we go. Awesome. So first, let's just implement the DBSIZE command, right? So this is supposed to return the size of the database, right? So first of all, let's just lock the database for reading because we're reading the size of the database. We're not writing any new changes to it. So let's just lock it only for reading. Then let's get the size of the database, which is going to be the length of the database store. And once we have that, let's unlock the reader over here, and then let's just return a value of type integer, and the actual number here will be the size. There we go. And that's all we need to do for the DBSIZE command. Now let's implement the FLUSHDB command. This is supposed to destroy the entire database, right? Now, there's two approaches to this. One is a very terrible approach, and the other is a very good approach. So when you think about destroying the entire database, you might make the mistake of basically just deleting every single key in the database, right? And the way to do that in Go is to just do something like `for key in the database store`, and you run the delete function on it, right? And I guess over here you're supposed to pass the database store and the key like that. This is, I mean, it gets the job done, but you're looping over the entire map to delete each key individually, and that's just not a good approach, right, in terms of performance and stuff. If you have thousands of keys, tens of thousands of keys, or even millions of keys. There are enterprise software out there that use millions of keys in their Redis caches, right? So this is obviously the worst approach you could pick. Instead of that, let's just remove all of this and just set the DB store to a completely new map, right? A completely new and empty map that we initialize over here. And that's going to just remove the previous database store completely. And yeah, that's all we need to do. So obviously, make sure to lock the mutex over here. And in this case, we're writing new changes to the database, so we need to lock it for writing as well. And unlock it down here when we're done. And then let's just return a value over here of type string, and the value will be "OK". So just a simple OK success message, right? And that's all we need to do to implement FLUSHDB. Now we've implemented both handlers and added them to the handlers list up here, so now we can actually test this out. Let's clear everything, run the Go file, or the Go server, sorry. Open up a client as well over here, and now we can try running the DBSIZE command, and it's giving me four. So this is probably coming from the AOF file over here, where we have a bunch of different, like, values over here backed up, right? So if I run the FLUSHDB command now, it returns the OK success message, and then if I try running DBSIZE again, it should give me zero. And yes, it does. So all of these things work now. Both of these commands work. I can try setting some new values over here, like name and age, and now the database size should be 2, which it is. And I can obviously run FLUSHDB, and now it's going to be 0. And if I try getting name or getting the age, it's gonna be nil because I flushed or deleted the database. So yeah, simple short video. We just implemented both of these new commands, FLUSHDB and DBSIZE. In the next video, or in the next couple of videos, I am planning to implement more complicated features, more complex features, features of Redis, things like database transactions. And let me actually just see what I am planning to do. I want to implement the hashing and checksum protection in the RDB file over here. So basically, I want to make sure that the bytes that we encode over here are the same bytes that are written to the file, right? So I want to implement checksum protection over there. I also want to implement database transactions and also implement the EXPIRE and the TTL (time to live) commands, which basically, what they do is—and by the way, the video is over. This is done. I'm just discussing future plans for this project—I want to implement the EXPIRE and the TTL (time to live) commands. And these are basically going to allow us to expire or delete certain keys after some time, right? So we can say something like, expire the name key over here, right, after let's say 30 seconds or 30 minutes, right? And it's going to automatically delete it for us. So yeah, things like that, and also eviction policies like LRU and LFU. Now, these are memory management policies in Redis, and they basically tell Redis how to handle the database when we run out of memory. So you know that Redis stores all of its data in memory by default, right? So what happens if we run out of memory, right? If the max memory is reached, that's where these eviction policies come into play, and that's what we're also going to implement in one of the future parts of this series. So stay tuned for that. And yeah, lots of cool things coming to this project. But yeah, thank you for watching this part. Thank you for supporting the series so far. Lots of cool new stuff coming. And yeah, thank you for watching. Like, share, subscribe, comments, reach out, whatever, right? And I will see you in the next video. Thank you for watching, and bye.

Share this article

Hassan Aziz pointing up

Dude, you’re at the bottom of my landing page.

Just book a call already if you’re that interested.

You scrolled all the way here.