From ab406a4be7e13ae6a2857d5b2924151feae4fd83 Mon Sep 17 00:00:00 2001 From: "Kyle J. Davis" Date: Fri, 5 Sep 2025 14:58:39 -0600 Subject: [PATCH 01/13] adds blog post about numbered databases and fixes style with bullets Signed-off-by: Kyle J. Davis --- .../images/move-db.drawio.png | Bin 0 -> 67150 bytes .../images/numbered-db.drawio.png | Bin 0 -> 31268 bytes .../images/zadd-move.drawio.png | Bin 0 -> 73304 bytes .../2025-09-10-numbered-databases/index.md | 83 ++++++++++++++++++ sass/_valkey.scss | 10 --- 5 files changed, 83 insertions(+), 10 deletions(-) create mode 100644 content/blog/2025-09-10-numbered-databases/images/move-db.drawio.png create mode 100644 content/blog/2025-09-10-numbered-databases/images/numbered-db.drawio.png create mode 100644 content/blog/2025-09-10-numbered-databases/images/zadd-move.drawio.png create mode 100644 content/blog/2025-09-10-numbered-databases/index.md diff --git a/content/blog/2025-09-10-numbered-databases/images/move-db.drawio.png b/content/blog/2025-09-10-numbered-databases/images/move-db.drawio.png new file mode 100644 index 0000000000000000000000000000000000000000..99378bb293767e468a90889d9a65fba818a6721d GIT binary patch literal 67150 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 IU>Eg&0Qp_-5&!@I literal 0 HcmV?d00001 diff --git a/content/blog/2025-09-10-numbered-databases/images/zadd-move.drawio.png b/content/blog/2025-09-10-numbered-databases/images/zadd-move.drawio.png new file mode 100644 index 0000000000000000000000000000000000000000..77cbce08ef7c2785a4b805000b1377cccb09d68f GIT binary patch literal 73304 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 C3#TLi literal 0 HcmV?d00001 diff --git a/content/blog/2025-09-10-numbered-databases/index.md b/content/blog/2025-09-10-numbered-databases/index.md new file mode 100644 index 00000000..1f9a1b27 --- /dev/null +++ b/content/blog/2025-09-10-numbered-databases/index.md @@ -0,0 +1,83 @@ ++++ +title= "Numbered “Databases” in Valkey 9.0" +description = "If you explore Valkey’s documentation you might run across a tantalizing feature called ‘numbered databases’ which allows you to separate the keyspace into (by default) 16 different databases. " +date= 2025-09-10 00:00:00 +authors= [ "kyledvs"] + +[extra] +featured = true +featured_image = "/blog/numbered-databases/images/move-db.drawio.png" ++++ + + +If you explore Valkey’s documentation you might run across a tantalizing feature called ‘numbered databases’ which allows you to separate the keyspace into (by default) 16 different databases. This has been around for more than 15 years in the preceding project. But, also, if you’ve done more research on numbered databases in the past you might have heard a advice like “don’t use them,” “they don’t scale,” and “they’re a bad idea.” Well, the forthcoming Valkey 9.0 changes many things with numbered databases and you’ll see in this post that advice definitely needs some updating. + +Today, a common way to conceptualize Valkey is that your keys represent a unique name for pointers to data in memory across a cluster of nodes. So, key `foo` is unique and deterministically linked to a specific node and on that node there is a memory address where the value resides. However, this misses one key (🥁) part: the database number. The reality is that key names belong to a specific numbered database and *aren’t unique* on a given instance of Valkey. To put this another way, if you have 16 numbered databases, Valkey can have the key `foo` 16 times with each one pointing to different data. + +Historically, when Valkey’s preceding project had the ability to cluster (before version 3.0.0), using multiple numbered database was fully supported. However, when clustering was implemented numbered databases weren’t included: a cluster had one database (DB 0) that spanned across the entire cluster. Why? I was personally involved with the community of the predecessor project and I think much of the discourse around number databases was lost to the sands of time, but there was a general feeling that users made wrong assumptions about numbered databases: then, and today, numbered databases do not provide any sort of multi-tenancy or resource isolation. To a degree, “database” is probably a bad name for this functionality: the best way to think about numbered databases is more as a numbered *namespace* for your keys (hence the scare quotes around database in the title of this piece). + +![one key, many databases](./images/numbered-db.drawio.png) + +In a world where using numbered databases in your application locked you into never going beyond a single node, the early advice made sense, however Valkey 9.0 adds the ability to have numbered databases on a cluster, changing everything about that advice. + +## Clustering and numbered databases + +As mentioned earlier, the key name dictates where the key lives in the cluster and this doesn’t change for numbered databases. As a refresher, [Valkey clustering](https://valkey.io/topics/cluster-tutorial/) takes the key name as a string, runs that through a CRC-16 function, then does a modulo of 16,384 which determines the ‘slot’. Each of these slots belong to a node in the cluster. For a numbered database, each slot contains all the numbered databases, so, carrying forward the idea that you can have the same key name in each database on a single instance, in Valkey 9.0 you can have the same key multiple times in a given slot, each in their own database. In other words, numbered databases do not affect clustering: the key is still the determinate factor in calculating slots. + +You can see this directly with [`CLUSTER KEYSLOT`](https://valkey.io/commands/cluster-keyslot/) and [`SELECT`](https://valkey.io/commands/select/). Take the following example: + +``` +> SELECT 0 +OK +> SET somekey hi +OK +> CLUSTER KEYSLOT somekey +(integer) 11058 +> SELECT 5 +OK +> SET somekey hello +OK +> CLUSTER KEYSLOT somekey +(integer) 11058 +``` + +Here the key `somekey` was set to two different values: ‘hi’ on database 0, and ‘hello’ on database 5, with `SELECT` altering the selected database. `CLUSTER KEYSLOT` was called twice: each one yielding the same slot number meaning this key will be assigned to the same node in the cluster, no matter which database is selected. + +Keep in mind that numbered databases cary the same clustering properties as other commands: operations that needs to span the entire keyspace will to be run on each node: + +* [`FLUSHDB`](https://valkey.io/commands/flushdb/) will flush the keys in the current database *on the connected node* +* [`SCAN`](https://valkey.io/commands/scan/) will iteratively return keys in the current database *on the connected node.* +* [`DBSIZE`](https://valkey.io/commands/dbsize/) will return the number of keys in the current database *on the connected node.* + +You get the picture: if something previously said it did something for the entire database, in cluster mode it really means for the connected node’s portion of the database. + +## Where to use numbered databases + +Numbered databases have many uses. The first thing that people often want to do is to run different applications on the same cluster. This *can* work out fine, but keep in mind that, even in Valkey 9, you’re only really namespacing - there is no resource isolation between databases. So, a busy application on database 0 will affect the performance of an application on another database. + +A similar use case would be running multiple instances of the *same* application on different databases. This might be a more compelling use case: multiple databases avoid any clashes in the key names and you’ll likely have a handle on resources required for each instance of an application when compared to different applications. However, same deal, there is no resource isolation. + +In both of these cases, you might have previously solved the problem with key prefixing (e.g. `app0:foo` and `app1:foo`) but numbered databases make your keys smaller (which equates to memory savings, especially with many keys), allows you to do some management steps easier (clear out an application with `FLUSHDB` on each node instead of an iterative delete by pattern on each node), and you don’t need to have key prefixing logic built into you application. + +An entirely different use of numbered databases is related to the [`MOVE`](https://valkey.io/commands/move/) command. `MOVE` allows you to change a key from one database to another *without copying the data,* meaning it uses very little resources and it’s an `O(1)` operation. This allows a couple of things: 1) you can effectively make data inaccessible from a database whilst keeping it on the same cluster node, and 2) you can replace a complex key atomically. + +Looking at the first use of `MOVE`: imagine you have some content, maybe a user submitted post, that is stored at the key “mycontent.” At some point this content gets flagged as needing to be reviewed. You might not want to *delete* this content but you also don’t want it accessible. In this case you take the content and `MOVE` it to a different database. Once it’s reviewed (or edited!) you can `MOVE` it back. Never does the data actually leave the node nor get copied. Whilst your use-case might not be the same as this, the pattern illustrates an operation useful in a variety of contexts. + +![now you see me, now you don't](./images/move-db.drawio.png) + +The second use of `MOVE` is similar to the first except it revolves around complex keys that contain many elements. Take, for example, a large sorted set. It’s not unusual for these keys to be quite large because the key contains thousands or millions of smaller elements. If you need to replace this key with one that contains different elements then you’d have to first `DEL` the original key, then `ZADD` thousands of elements. Doing this in a transaction would be expensive and monopolize the node, and without a transaction, it would reveal a (potentially undesirable) partial state. Instead, with multiple databases, you build up new a complex key on a different database (under no urgency) and do a much simpler `MULTI` / `EXEC` transaction of of `DEL` followed by `MOVE` to atomically make the new complex key available to the database being used to serve commands without the chance of a partial state. + +![show me it when its done](./images/zadd-move.drawio.png) + +Finally, multiple databases are a useful debugging tool. When you’re building an application it can be difficult to see what happens inside Valkey when you make a change. If you have multiple databases you can run your original code on one database and the changed version on a different database then you can more easily see changes in how data looks in Valkey by just swapping between databases. While this is likely the least obvious use case and certainly not one that is relevant for production workloads, just saves complexity around having multiple clusters with potentially different configurations or having to stop/start your database. + +## Gotchas and future work + +Aside from the aforementioned lack of resource isolation, numbered databases in clustered Valkey have a few places that you need to look out for today. First, right now numbered databases don’t have dedicated metrics, so it can be hard to gain insights into per-database resource usage. Second, the ACL system doesn’t address numbered databases, so you can’t meaningfully restrict access to databases. Finally, while numbered databases are well supported in client libraries there are rough edges: + +* Some client libraries artificially restrict usage to a single database in cluster mode. +* Pooled clients may naively manage the selected database, so a client returned to the pool after running SELECT might retain the database number in subsequent usage. A similar situation is possible for multiplexed clients. + +In general, watch out for three assumptions: 1) the selected database is always 0, 2) their is only one database in cluster mode, and 3) if there is multiple databases in use it isn’t in cluster mode. None of these are true in Valkey 9.0. + +With this in mind, Valkey 9.0 gives you the ability to divvy up that keyspace into nice neat numbered databases and spread them out over a whatever cluster you have. So, get rid of that old, outdated advice and start using them, seeing how they scale, and what a good idea number databases actually are for Valkey 9.0. diff --git a/sass/_valkey.scss b/sass/_valkey.scss index df1222ce..d2fc6890 100644 --- a/sass/_valkey.scss +++ b/sass/_valkey.scss @@ -1071,16 +1071,6 @@ aside { color: #718096; } - ul { - list-style: none; - padding: 0; - margin: 0 0 2rem 0; - - li { - a {} - } - } - img { display: block; width: 100%; From 4e1a48a94e536e6cad926ca9e5e5e801b83a0ece Mon Sep 17 00:00:00 2001 From: "Kyle J. Davis" Date: Mon, 15 Sep 2025 15:46:57 -0600 Subject: [PATCH 02/13] addresses feedback Signed-off-by: Kyle J. Davis --- .../2025-09-10-numbered-databases/index.md | 37 ++++++++++++------- sass/_valkey.scss | 5 +++ 2 files changed, 28 insertions(+), 14 deletions(-) diff --git a/content/blog/2025-09-10-numbered-databases/index.md b/content/blog/2025-09-10-numbered-databases/index.md index 1f9a1b27..717aa1ce 100644 --- a/content/blog/2025-09-10-numbered-databases/index.md +++ b/content/blog/2025-09-10-numbered-databases/index.md @@ -12,13 +12,13 @@ featured_image = "/blog/numbered-databases/images/move-db.drawio.png" If you explore Valkey’s documentation you might run across a tantalizing feature called ‘numbered databases’ which allows you to separate the keyspace into (by default) 16 different databases. This has been around for more than 15 years in the preceding project. But, also, if you’ve done more research on numbered databases in the past you might have heard a advice like “don’t use them,” “they don’t scale,” and “they’re a bad idea.” Well, the forthcoming Valkey 9.0 changes many things with numbered databases and you’ll see in this post that advice definitely needs some updating. -Today, a common way to conceptualize Valkey is that your keys represent a unique name for pointers to data in memory across a cluster of nodes. So, key `foo` is unique and deterministically linked to a specific node and on that node there is a memory address where the value resides. However, this misses one key (🥁) part: the database number. The reality is that key names belong to a specific numbered database and *aren’t unique* on a given instance of Valkey. To put this another way, if you have 16 numbered databases, Valkey can have the key `foo` 16 times with each one pointing to different data. - -Historically, when Valkey’s preceding project had the ability to cluster (before version 3.0.0), using multiple numbered database was fully supported. However, when clustering was implemented numbered databases weren’t included: a cluster had one database (DB 0) that spanned across the entire cluster. Why? I was personally involved with the community of the predecessor project and I think much of the discourse around number databases was lost to the sands of time, but there was a general feeling that users made wrong assumptions about numbered databases: then, and today, numbered databases do not provide any sort of multi-tenancy or resource isolation. To a degree, “database” is probably a bad name for this functionality: the best way to think about numbered databases is more as a numbered *namespace* for your keys (hence the scare quotes around database in the title of this piece). +Today, a common way to conceptualize Valkey is that your keys represent a unique name for pointers to data in memory across a cluster of nodes. So, key `foo` is unique and deterministically linked to a specific node and on that node there is a memory address where the value resides. However, this misses one important detail: the database number. The reality is that key names belong to a specific numbered database and *aren’t unique* on a given instance of Valkey. To put this another way, if you have 16 numbered databases, Valkey can have the key `foo` as many times as there are numbered databases with each one pointing to different data. ![one key, many databases](./images/numbered-db.drawio.png) -In a world where using numbered databases in your application locked you into never going beyond a single node, the early advice made sense, however Valkey 9.0 adds the ability to have numbered databases on a cluster, changing everything about that advice. +Historically, before Valkey’s preceding project had the ability to cluster (before version 3.0.0), using multiple numbered databases was fully supported. However, when clustering was implemented numbered databases weren’t included: a cluster had one database (DB 0) that spanned across the entire cluster. In a world where using numbered databases in your application locked you into never going beyond a single node, the early advice made sense, however Valkey 9.0 adds the ability to have numbered databases on a cluster, changing everything about that advice. + +Why bring this feature to cluster mode in Valkey 9.0? In the intervening years since numbered databases were left out of the cluster spec, users have found a number of very handy patterns that were unfortunately limited without numbered databases. However, numbered databases aren't a panacea: read on to find out when you should stick to DB 0 and when to go for a numbered database. ## Clustering and numbered databases @@ -43,21 +43,23 @@ OK Here the key `somekey` was set to two different values: ‘hi’ on database 0, and ‘hello’ on database 5, with `SELECT` altering the selected database. `CLUSTER KEYSLOT` was called twice: each one yielding the same slot number meaning this key will be assigned to the same node in the cluster, no matter which database is selected. -Keep in mind that numbered databases cary the same clustering properties as other commands: operations that needs to span the entire keyspace will to be run on each node: +## What are numbered databases and limits + +If you take away one thing from this blog it should be this: **numbered databases are a form of namespacing**. Consequently, they do not provide any form of resource isolation nor do they change the properties of how a Valkey cluster works. + +It's tempting to point a bunch of applications to a single Valkey cluster with each application taking it's own database. While this certainly *can* work, it works without resource isolation and this setup can suffer from classic noisy neighbour problems: busy applications will affect the others using the same cluster. Most of the time you'll be better off just having distinct clusters for each application if you're worried about resources. + +In a cluster, the keyspace of each database is still split amongst all the nodes. As a consequence, operations that need to span the entire keyspace will to be run on each node: * [`FLUSHDB`](https://valkey.io/commands/flushdb/) will flush the keys in the current database *on the connected node* * [`SCAN`](https://valkey.io/commands/scan/) will iteratively return keys in the current database *on the connected node.* * [`DBSIZE`](https://valkey.io/commands/dbsize/) will return the number of keys in the current database *on the connected node.* -You get the picture: if something previously said it did something for the entire database, in cluster mode it really means for the connected node’s portion of the database. +You get the picture: if a command previously said it did something for the entire database, in cluster mode it really means for the connected node’s portion of the database. These are especially important to understand if you're planning to move an application built for non-clustered, numbered databases to a cluster. ## Where to use numbered databases -Numbered databases have many uses. The first thing that people often want to do is to run different applications on the same cluster. This *can* work out fine, but keep in mind that, even in Valkey 9, you’re only really namespacing - there is no resource isolation between databases. So, a busy application on database 0 will affect the performance of an application on another database. - -A similar use case would be running multiple instances of the *same* application on different databases. This might be a more compelling use case: multiple databases avoid any clashes in the key names and you’ll likely have a handle on resources required for each instance of an application when compared to different applications. However, same deal, there is no resource isolation. - -In both of these cases, you might have previously solved the problem with key prefixing (e.g. `app0:foo` and `app1:foo`) but numbered databases make your keys smaller (which equates to memory savings, especially with many keys), allows you to do some management steps easier (clear out an application with `FLUSHDB` on each node instead of an iterative delete by pattern on each node), and you don’t need to have key prefixing logic built into you application. +The most straight forward use case of numbered databases is when you need to separate your data logically and you can tolerate the effects of resource sharing (see above). This might be something like keeping customer data separated from one another or combining applications on to a single cluster when resources are unlikely to be an issue. In a similar manner, multiple databases are a useful debugging tool. When you’re building an application it can be difficult to see what happens inside Valkey when you make a change. If you have multiple databases you can run your original code on one database and the changed version on a different database then you can more easily see changes in how data looks in Valkey by just the connection swapping between databases. This is also a useful pattern during a migration when you want your old data to stick around while your new data is populated. An entirely different use of numbered databases is related to the [`MOVE`](https://valkey.io/commands/move/) command. `MOVE` allows you to change a key from one database to another *without copying the data,* meaning it uses very little resources and it’s an `O(1)` operation. This allows a couple of things: 1) you can effectively make data inaccessible from a database whilst keeping it on the same cluster node, and 2) you can replace a complex key atomically. @@ -69,13 +71,20 @@ The second use of `MOVE` is similar to the first except it revolves around compl ![show me it when its done](./images/zadd-move.drawio.png) -Finally, multiple databases are a useful debugging tool. When you’re building an application it can be difficult to see what happens inside Valkey when you make a change. If you have multiple databases you can run your original code on one database and the changed version on a different database then you can more easily see changes in how data looks in Valkey by just swapping between databases. While this is likely the least obvious use case and certainly not one that is relevant for production workloads, just saves complexity around having multiple clusters with potentially different configurations or having to stop/start your database. +This is really a form of temporal namespacing: you're taking advantage of the namespace to have two active keys under the same name both of which can be read and manipulated. You can apply this pattern to other cases: anyplace you want to make a key inaccessible for a period of time. + +> **How is key prefixing different than numbered databases?** Some of the patterns in this blog can be achieved without numbered databases and instead with key prefixing (e.g. `app0:...`, `app1:...`). Key prefixing has a few downsides when compared to numbered databases: +> * Prefixes add up at scale. Millions of keys each with repeated prefixes over the span of the whole cluster means less RAM for data. While each database does have a memory overhead it is linear relative to the number of databases, not keys. +> * Databases are transparent to your application. To support prefixing, either your application or your client library has to be able to interpolate the prefix into each key. With numbered databases, the changes can be as simple as a number in the connection URI, not to each key name. +> * Databases avoid pattern-based iterations. Having all your keys in DB 0 then needing to iterate over the entire keyspace to affect a specific pattern is expensive and complicated. If your keys are separated into databases, this both subsets that iteration and enables some database wide commands (i.e. `FLUSHDB` instead of trying to delete keys by a pattern). ## Gotchas and future work -Aside from the aforementioned lack of resource isolation, numbered databases in clustered Valkey have a few places that you need to look out for today. First, right now numbered databases don’t have dedicated metrics, so it can be hard to gain insights into per-database resource usage. Second, the ACL system doesn’t address numbered databases, so you can’t meaningfully restrict access to databases. Finally, while numbered databases are well supported in client libraries there are rough edges: +Aside from the aforementioned lack of resource isolation, numbered databases in clustered Valkey have a few places that you need to look out for today. First, right now numbered databases don’t have dedicated metrics, so it can be hard to gain insights into per-database resource usage. Second, the ACL system doesn’t currently address numbered databases, so you can’t meaningfully restrict access to databases (at time of writing, there is an [open pull request that addresses this](https://github.com/valkey-io/valkey/pull/2309)). Unlike in the previous project, databases are an active area of work for the Valkey project and the database abstraction holds potential as a way to implement new features. + +Finally, while numbered databases are well supported in client libraries there are rough edges: -* Some client libraries artificially restrict usage to a single database in cluster mode. +* Some client libraries artificially restrict usage to a single database in cluster mode, * Pooled clients may naively manage the selected database, so a client returned to the pool after running SELECT might retain the database number in subsequent usage. A similar situation is possible for multiplexed clients. In general, watch out for three assumptions: 1) the selected database is always 0, 2) their is only one database in cluster mode, and 3) if there is multiple databases in use it isn’t in cluster mode. None of these are true in Valkey 9.0. diff --git a/sass/_valkey.scss b/sass/_valkey.scss index d2fc6890..b871bec8 100644 --- a/sass/_valkey.scss +++ b/sass/_valkey.scss @@ -1954,6 +1954,11 @@ html.banner-hidden .banner { border: 1px solid #072150; } +blockquote { + display: block; + margin-block-start: 1em; + margin-block-end: 1em; +} .icon-social { width: 18px; height: 18px; From 4718970f14cfbead1101ffe8e5545e504f84c0f6 Mon Sep 17 00:00:00 2001 From: "Kyle J. Davis" Date: Wed, 17 Sep 2025 14:44:05 -0600 Subject: [PATCH 03/13] Update content/blog/2025-09-10-numbered-databases/index.md Co-authored-by: Ran Shidlansik Signed-off-by: Kyle J. Davis --- content/blog/2025-09-10-numbered-databases/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/blog/2025-09-10-numbered-databases/index.md b/content/blog/2025-09-10-numbered-databases/index.md index 717aa1ce..f86a7b0c 100644 --- a/content/blog/2025-09-10-numbered-databases/index.md +++ b/content/blog/2025-09-10-numbered-databases/index.md @@ -47,7 +47,7 @@ Here the key `somekey` was set to two different values: ‘hi’ on database 0, If you take away one thing from this blog it should be this: **numbered databases are a form of namespacing**. Consequently, they do not provide any form of resource isolation nor do they change the properties of how a Valkey cluster works. -It's tempting to point a bunch of applications to a single Valkey cluster with each application taking it's own database. While this certainly *can* work, it works without resource isolation and this setup can suffer from classic noisy neighbour problems: busy applications will affect the others using the same cluster. Most of the time you'll be better off just having distinct clusters for each application if you're worried about resources. +It's tempting to point a bunch of applications to a single Valkey cluster with each application taking it's own database. While this certainly *can* work, it works without resource isolation and this setup can suffer from classic noisy neighbour problems: busy applications will affect the others using the same cluster. Most of the time you'll be better off just having distinct clusters for each application if you're worried about resource sharing. In a cluster, the keyspace of each database is still split amongst all the nodes. As a consequence, operations that need to span the entire keyspace will to be run on each node: From 945a9667d7b103aaa70df3ab0a1f7b8a16aa5f0c Mon Sep 17 00:00:00 2001 From: "Kyle J. Davis" Date: Thu, 18 Sep 2025 07:29:45 -0600 Subject: [PATCH 04/13] qualifies metrics statement --- content/blog/2025-09-10-numbered-databases/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/blog/2025-09-10-numbered-databases/index.md b/content/blog/2025-09-10-numbered-databases/index.md index 717aa1ce..cf79b15f 100644 --- a/content/blog/2025-09-10-numbered-databases/index.md +++ b/content/blog/2025-09-10-numbered-databases/index.md @@ -80,7 +80,7 @@ This is really a form of temporal namespacing: you're taking advantage of the na ## Gotchas and future work -Aside from the aforementioned lack of resource isolation, numbered databases in clustered Valkey have a few places that you need to look out for today. First, right now numbered databases don’t have dedicated metrics, so it can be hard to gain insights into per-database resource usage. Second, the ACL system doesn’t currently address numbered databases, so you can’t meaningfully restrict access to databases (at time of writing, there is an [open pull request that addresses this](https://github.com/valkey-io/valkey/pull/2309)). Unlike in the previous project, databases are an active area of work for the Valkey project and the database abstraction holds potential as a way to implement new features. +Aside from the aforementioned lack of resource isolation, numbered databases in clustered Valkey have a few places that you need to look out for today. First, right now numbered databases don’t have a lot of dedicated metrics, so it can be hard to gain insights into per-database resource usage. Second, the ACL system doesn’t currently address numbered databases, so you can’t meaningfully restrict access to databases (at time of writing, there is an [open pull request that addresses this](https://github.com/valkey-io/valkey/pull/2309)). Unlike in the previous project, databases are an active area of work for the Valkey project and the database abstraction holds potential as a way to implement new features. Finally, while numbered databases are well supported in client libraries there are rough edges: From a9e873b2fc4445e4280a6beb519acf9b77ac86aa Mon Sep 17 00:00:00 2001 From: "Kyle J. Davis" Date: Thu, 18 Sep 2025 07:46:06 -0600 Subject: [PATCH 05/13] adds link for memory overhead discussion Signed-off-by: Kyle J. Davis --- content/blog/2025-09-10-numbered-databases/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/blog/2025-09-10-numbered-databases/index.md b/content/blog/2025-09-10-numbered-databases/index.md index cf79b15f..53476ff9 100644 --- a/content/blog/2025-09-10-numbered-databases/index.md +++ b/content/blog/2025-09-10-numbered-databases/index.md @@ -74,7 +74,7 @@ The second use of `MOVE` is similar to the first except it revolves around compl This is really a form of temporal namespacing: you're taking advantage of the namespace to have two active keys under the same name both of which can be read and manipulated. You can apply this pattern to other cases: anyplace you want to make a key inaccessible for a period of time. > **How is key prefixing different than numbered databases?** Some of the patterns in this blog can be achieved without numbered databases and instead with key prefixing (e.g. `app0:...`, `app1:...`). Key prefixing has a few downsides when compared to numbered databases: -> * Prefixes add up at scale. Millions of keys each with repeated prefixes over the span of the whole cluster means less RAM for data. While each database does have a memory overhead it is linear relative to the number of databases, not keys. +> * Prefixes add up at scale. Millions of keys each with repeated prefixes over the span of the whole cluster means less RAM for data. While each database does have a memory overhead it is linear relative to the number of databases used, not keys. For a deeper look a how numbered database memory overhead works, including using 10 million databases, read the comments on [valkey-io/valkey#1609](https://github.com/valkey-io/valkey/pull/1609#issuecomment-2616366819). > * Databases are transparent to your application. To support prefixing, either your application or your client library has to be able to interpolate the prefix into each key. With numbered databases, the changes can be as simple as a number in the connection URI, not to each key name. > * Databases avoid pattern-based iterations. Having all your keys in DB 0 then needing to iterate over the entire keyspace to affect a specific pattern is expensive and complicated. If your keys are separated into databases, this both subsets that iteration and enables some database wide commands (i.e. `FLUSHDB` instead of trying to delete keys by a pattern). From 6e6348054d1b53231d37b18d81b30ac90ae5e25f Mon Sep 17 00:00:00 2001 From: "Kyle J. Davis" Date: Thu, 18 Sep 2025 08:02:05 -0600 Subject: [PATCH 06/13] changed node language for non-clustered Valkey Signed-off-by: Kyle J. Davis --- content/blog/2025-09-10-numbered-databases/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/blog/2025-09-10-numbered-databases/index.md b/content/blog/2025-09-10-numbered-databases/index.md index 53476ff9..a2cceb9e 100644 --- a/content/blog/2025-09-10-numbered-databases/index.md +++ b/content/blog/2025-09-10-numbered-databases/index.md @@ -16,7 +16,7 @@ Today, a common way to conceptualize Valkey is that your keys represent a unique ![one key, many databases](./images/numbered-db.drawio.png) -Historically, before Valkey’s preceding project had the ability to cluster (before version 3.0.0), using multiple numbered databases was fully supported. However, when clustering was implemented numbered databases weren’t included: a cluster had one database (DB 0) that spanned across the entire cluster. In a world where using numbered databases in your application locked you into never going beyond a single node, the early advice made sense, however Valkey 9.0 adds the ability to have numbered databases on a cluster, changing everything about that advice. +Historically, before Valkey’s preceding project had the ability to cluster (before version 3.0.0), using multiple numbered databases was fully supported. However, when clustering was implemented numbered databases weren’t included: a cluster had one database (DB 0) that spanned across the entire cluster. In a world where using numbered databases in your application locked you into never going to a cluster, the early advice made sense, however Valkey 9.0 adds the ability to have numbered databases on a cluster, changing everything about that advice. Why bring this feature to cluster mode in Valkey 9.0? In the intervening years since numbered databases were left out of the cluster spec, users have found a number of very handy patterns that were unfortunately limited without numbered databases. However, numbered databases aren't a panacea: read on to find out when you should stick to DB 0 and when to go for a numbered database. From 264f942083a1697ac68d7a00a8b817d3f7119afc Mon Sep 17 00:00:00 2001 From: "Kyle J. Davis" Date: Thu, 18 Sep 2025 13:57:38 -0600 Subject: [PATCH 07/13] fixed styling issue with block quotes, update description Signed-off-by: Kyle J. Davis --- content/blog/2025-09-10-numbered-databases/index.md | 6 +++--- sass/_valkey.scss | 3 +++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/content/blog/2025-09-10-numbered-databases/index.md b/content/blog/2025-09-10-numbered-databases/index.md index a2cceb9e..d8c0b52a 100644 --- a/content/blog/2025-09-10-numbered-databases/index.md +++ b/content/blog/2025-09-10-numbered-databases/index.md @@ -1,6 +1,6 @@ +++ title= "Numbered “Databases” in Valkey 9.0" -description = "If you explore Valkey’s documentation you might run across a tantalizing feature called ‘numbered databases’ which allows you to separate the keyspace into (by default) 16 different databases. " +description = "Valkey 9.0 brings new namespacing abilities to cluster mode. In this blog you'll learn about numbered databases, how they've changed in the recent release, limitations, and how you can use them to efficiently solve a variety of otherwise challenging problems." date= 2025-09-10 00:00:00 authors= [ "kyledvs"] @@ -12,7 +12,7 @@ featured_image = "/blog/numbered-databases/images/move-db.drawio.png" If you explore Valkey’s documentation you might run across a tantalizing feature called ‘numbered databases’ which allows you to separate the keyspace into (by default) 16 different databases. This has been around for more than 15 years in the preceding project. But, also, if you’ve done more research on numbered databases in the past you might have heard a advice like “don’t use them,” “they don’t scale,” and “they’re a bad idea.” Well, the forthcoming Valkey 9.0 changes many things with numbered databases and you’ll see in this post that advice definitely needs some updating. -Today, a common way to conceptualize Valkey is that your keys represent a unique name for pointers to data in memory across a cluster of nodes. So, key `foo` is unique and deterministically linked to a specific node and on that node there is a memory address where the value resides. However, this misses one important detail: the database number. The reality is that key names belong to a specific numbered database and *aren’t unique* on a given instance of Valkey. To put this another way, if you have 16 numbered databases, Valkey can have the key `foo` as many times as there are numbered databases with each one pointing to different data. +Today, a common way to conceptualize Valkey is that your keys represent a unique name for pointers to data in memory across a cluster of nodes. So, key `foo` is unique and deterministically linked to a specific node and on that node there is a memory address where the value resides. However, this misses one important detail: the database number. The reality is that key names belong to a specific numbered database and *aren’t unique* on a given instance of Valkey. To put this another way, Valkey can have the key `foo` as many times as there are numbered databases with each one pointing to different data. ![one key, many databases](./images/numbered-db.drawio.png) @@ -85,7 +85,7 @@ Aside from the aforementioned lack of resource isolation, numbered databases in Finally, while numbered databases are well supported in client libraries there are rough edges: * Some client libraries artificially restrict usage to a single database in cluster mode, -* Pooled clients may naively manage the selected database, so a client returned to the pool after running SELECT might retain the database number in subsequent usage. A similar situation is possible for multiplexed clients. +* Pooled clients may naively manage the selected database, so a client returned to the pool after running `SELECT` might retain the database number in subsequent usage. A similar sitauation is possible for multiplexed clients. In general, watch out for three assumptions: 1) the selected database is always 0, 2) their is only one database in cluster mode, and 3) if there is multiple databases in use it isn’t in cluster mode. None of these are true in Valkey 9.0. diff --git a/sass/_valkey.scss b/sass/_valkey.scss index b871bec8..17ffddce 100644 --- a/sass/_valkey.scss +++ b/sass/_valkey.scss @@ -1958,6 +1958,9 @@ blockquote { display: block; margin-block-start: 1em; margin-block-end: 1em; + margin-left: 0; + padding-left: 1.5em; + border-left: 3px solid $lf-light-blue; } .icon-social { width: 18px; From b5d487cbf5b5677d98202513b4c4a7b88489cea1 Mon Sep 17 00:00:00 2001 From: "Kyle J. Davis" Date: Thu, 18 Sep 2025 14:19:00 -0600 Subject: [PATCH 08/13] refactor intro Signed-off-by: Kyle J. Davis --- content/blog/2025-09-10-numbered-databases/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/blog/2025-09-10-numbered-databases/index.md b/content/blog/2025-09-10-numbered-databases/index.md index d8c0b52a..aa748e64 100644 --- a/content/blog/2025-09-10-numbered-databases/index.md +++ b/content/blog/2025-09-10-numbered-databases/index.md @@ -10,7 +10,7 @@ featured_image = "/blog/numbered-databases/images/move-db.drawio.png" +++ -If you explore Valkey’s documentation you might run across a tantalizing feature called ‘numbered databases’ which allows you to separate the keyspace into (by default) 16 different databases. This has been around for more than 15 years in the preceding project. But, also, if you’ve done more research on numbered databases in the past you might have heard a advice like “don’t use them,” “they don’t scale,” and “they’re a bad idea.” Well, the forthcoming Valkey 9.0 changes many things with numbered databases and you’ll see in this post that advice definitely needs some updating. +If you explore Valkey’s documentation you might run across a feature called ‘numbered databases’ which allows you to separate the keyspace into (by default) 16 different databases. Digging into this feature reveals tantalizing ways to avoid key prefixing, house different workloads together on Valkey, and even perform patterns that are otherwise clunky. You'll also see that this has been around for more than 15 years in the preceding project. However, if you’ve done more research outside of the documentation on numbered databases you might run across a advice like “don’t use them,” “they don’t scale,” and “they’re a bad idea.” Well, the forthcoming Valkey 9.0 changes many things with numbered databases and you’ll see in this post that advice definitely needs some updating. Today, a common way to conceptualize Valkey is that your keys represent a unique name for pointers to data in memory across a cluster of nodes. So, key `foo` is unique and deterministically linked to a specific node and on that node there is a memory address where the value resides. However, this misses one important detail: the database number. The reality is that key names belong to a specific numbered database and *aren’t unique* on a given instance of Valkey. To put this another way, Valkey can have the key `foo` as many times as there are numbered databases with each one pointing to different data. From 93768d61f7cb7e2f22bc39f681d2158a90ffe4fc Mon Sep 17 00:00:00 2001 From: "Kyle J. Davis" Date: Thu, 18 Sep 2025 14:36:07 -0600 Subject: [PATCH 09/13] refactoring Signed-off-by: Kyle J. Davis --- content/blog/2025-09-10-numbered-databases/index.md | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/content/blog/2025-09-10-numbered-databases/index.md b/content/blog/2025-09-10-numbered-databases/index.md index aa748e64..94056f46 100644 --- a/content/blog/2025-09-10-numbered-databases/index.md +++ b/content/blog/2025-09-10-numbered-databases/index.md @@ -45,11 +45,9 @@ Here the key `somekey` was set to two different values: ‘hi’ on database 0, ## What are numbered databases and limits -If you take away one thing from this blog it should be this: **numbered databases are a form of namespacing**. Consequently, they do not provide any form of resource isolation nor do they change the properties of how a Valkey cluster works. +If you take away one thing from this blog it should be this: **numbered databases are a form of namespacing**. Consequently, they do not provide any form of resource isolation. It's tempting to point a bunch of applications to a single Valkey cluster with each application taking it's own database. While this certainly *can* work, it works without resource isolation and this setup can suffer from classic noisy neighbour problems: busy applications will affect the others using the same cluster. If you're worried about resources, most of the time you'll be better off just having distinct clusters for each application instead of numbered databases. -It's tempting to point a bunch of applications to a single Valkey cluster with each application taking it's own database. While this certainly *can* work, it works without resource isolation and this setup can suffer from classic noisy neighbour problems: busy applications will affect the others using the same cluster. Most of the time you'll be better off just having distinct clusters for each application if you're worried about resources. - -In a cluster, the keyspace of each database is still split amongst all the nodes. As a consequence, operations that need to span the entire keyspace will to be run on each node: +Likewise, numbered databases also do not change the properties of how a Valkey cluster works. The keyspace of each database is still split amongst all the nodes. As a consequence, operations that need to span the entire keyspace will to be run on each node: * [`FLUSHDB`](https://valkey.io/commands/flushdb/) will flush the keys in the current database *on the connected node* * [`SCAN`](https://valkey.io/commands/scan/) will iteratively return keys in the current database *on the connected node.* @@ -85,7 +83,7 @@ Aside from the aforementioned lack of resource isolation, numbered databases in Finally, while numbered databases are well supported in client libraries there are rough edges: * Some client libraries artificially restrict usage to a single database in cluster mode, -* Pooled clients may naively manage the selected database, so a client returned to the pool after running `SELECT` might retain the database number in subsequent usage. A similar sitauation is possible for multiplexed clients. +* Pooled clients may naively manage the selected database, so a client returned to the pool after running `SELECT` might retain the database number in subsequent usage. A similar situation is possible for multiplexed clients. In general, watch out for three assumptions: 1) the selected database is always 0, 2) their is only one database in cluster mode, and 3) if there is multiple databases in use it isn’t in cluster mode. None of these are true in Valkey 9.0. From 7800e4273d73de0c4696eaa6125c9146fa7cd9cf Mon Sep 17 00:00:00 2001 From: "Kyle J. Davis" Date: Wed, 24 Sep 2025 14:57:38 -0600 Subject: [PATCH 10/13] Update content/blog/2025-09-10-numbered-databases/index.md Co-authored-by: Madelyn Olson Signed-off-by: Kyle J. Davis --- content/blog/2025-09-10-numbered-databases/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/blog/2025-09-10-numbered-databases/index.md b/content/blog/2025-09-10-numbered-databases/index.md index 7c526115..72ba9de7 100644 --- a/content/blog/2025-09-10-numbered-databases/index.md +++ b/content/blog/2025-09-10-numbered-databases/index.md @@ -10,7 +10,7 @@ featured_image = "/blog/numbered-databases/images/move-db.drawio.png" +++ -If you explore Valkey’s documentation you might run across a feature called ‘numbered databases’ which allows you to separate the keyspace into (by default) 16 different databases. Digging into this feature reveals tantalizing ways to avoid key prefixing, house different workloads together on Valkey, and even perform patterns that are otherwise clunky. You'll also see that this has been around for more than 15 years in the preceding project. However, if you’ve done more research outside of the documentation on numbered databases you might run across a advice like “don’t use them,” “they don’t scale,” and “they’re a bad idea.” Well, the forthcoming Valkey 9.0 changes many things with numbered databases and you’ll see in this post that advice definitely needs some updating. +If you explore Valkey’s documentation you might run across a feature called ‘numbered databases’ which allows you to separate the keyspace into (by default) 16 different databases. Digging into this feature reveals tantalizing ways to avoid key prefixing, house different workloads together on Valkey, and even perform patterns that are otherwise clunky. However, if you’ve done more research outside of the documentation on numbered databases you might run across a advice like “don’t use them,” “they don’t scale,” and “they’re a bad idea.” Well, the forthcoming Valkey 9.0 changes many things with numbered databases and you’ll see in this post that advice definitely needs some updating. Today, a common way to conceptualize Valkey is that your keys represent a unique name for pointers to data in memory across a cluster of nodes. So, key `foo` is unique and deterministically linked to a specific node and on that node there is a memory address where the value resides. However, this misses one important detail: the database number. The reality is that key names belong to a specific numbered database and *aren’t unique* on a given instance of Valkey. To put this another way, Valkey can have the key `foo` as many times as there are numbered databases with each one pointing to different data. From 77aac71c25469e46a76d2af3f5c99a1dbbf25811 Mon Sep 17 00:00:00 2001 From: "Kyle J. Davis" Date: Wed, 24 Sep 2025 14:58:27 -0600 Subject: [PATCH 11/13] Update content/blog/2025-09-10-numbered-databases/index.md Co-authored-by: Madelyn Olson Signed-off-by: Kyle J. Davis --- content/blog/2025-09-10-numbered-databases/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/blog/2025-09-10-numbered-databases/index.md b/content/blog/2025-09-10-numbered-databases/index.md index 72ba9de7..ac7f30a9 100644 --- a/content/blog/2025-09-10-numbered-databases/index.md +++ b/content/blog/2025-09-10-numbered-databases/index.md @@ -72,7 +72,7 @@ The second use of `MOVE` is similar to the first except it revolves around compl This is really a form of temporal namespacing: you're taking advantage of the namespace to have two active keys under the same name both of which can be read and manipulated. You can apply this pattern to other cases: anyplace you want to make a key inaccessible for a period of time. > **How is key prefixing different than numbered databases?** Some of the patterns in this blog can be achieved without numbered databases and instead with key prefixing (e.g. `app0:...`, `app1:...`). Key prefixing has a few downsides when compared to numbered databases: -> * Prefixes add up at scale. Millions of keys each with repeated prefixes over the span of the whole cluster means less RAM for data. While each database does have a memory overhead it is linear relative to the number of databases used, not keys. For a deeper look a how numbered database memory overhead works, including using 10 million databases, read the comments on [valkey-io/valkey#1609](https://github.com/valkey-io/valkey/pull/1609#issuecomment-2616366819). +> * Prefixes add up at scale. Millions of keys each with repeated prefixes over the span of the whole cluster means less RAM for data. While each database does have a memory overhead it is linear relative to the number of databases used, not keys. For a deeper look at how numbered database memory overhead works, including using 10 million databases, read the comments on [valkey-io/valkey#1609](https://github.com/valkey-io/valkey/pull/1609#issuecomment-2616366819). > * Databases are transparent to your application. To support prefixing, either your application or your client library has to be able to interpolate the prefix into each key. With numbered databases, the changes can be as simple as a number in the connection URI, not to each key name. > * Databases avoid pattern-based iterations. Having all your keys in DB 0 then needing to iterate over the entire keyspace to affect a specific pattern is expensive and complicated. If your keys are separated into databases, this both subsets that iteration and enables some database wide commands (i.e. `FLUSHDB` instead of trying to delete keys by a pattern). From b0a42411cb43fab2669aab051319b7828e839657 Mon Sep 17 00:00:00 2001 From: "Kyle J. Davis" Date: Wed, 24 Sep 2025 15:17:02 -0600 Subject: [PATCH 12/13] fixes from feedback, typos, and date update Signed-off-by: Kyle J. Davis --- .../images/move-db.drawio.png | Bin .../images/numbered-db.drawio.png | Bin .../images/zadd-move.drawio.png | Bin .../index.md | 18 ++++++++++-------- 4 files changed, 10 insertions(+), 8 deletions(-) rename content/blog/{2025-09-10-numbered-databases => 2025-09-25-numbered-databases}/images/move-db.drawio.png (100%) rename content/blog/{2025-09-10-numbered-databases => 2025-09-25-numbered-databases}/images/numbered-db.drawio.png (100%) rename content/blog/{2025-09-10-numbered-databases => 2025-09-25-numbered-databases}/images/zadd-move.drawio.png (100%) rename content/blog/{2025-09-10-numbered-databases => 2025-09-25-numbered-databases}/index.md (88%) diff --git a/content/blog/2025-09-10-numbered-databases/images/move-db.drawio.png b/content/blog/2025-09-25-numbered-databases/images/move-db.drawio.png similarity index 100% rename from content/blog/2025-09-10-numbered-databases/images/move-db.drawio.png rename to content/blog/2025-09-25-numbered-databases/images/move-db.drawio.png diff --git a/content/blog/2025-09-10-numbered-databases/images/numbered-db.drawio.png b/content/blog/2025-09-25-numbered-databases/images/numbered-db.drawio.png similarity index 100% rename from content/blog/2025-09-10-numbered-databases/images/numbered-db.drawio.png rename to content/blog/2025-09-25-numbered-databases/images/numbered-db.drawio.png diff --git a/content/blog/2025-09-10-numbered-databases/images/zadd-move.drawio.png b/content/blog/2025-09-25-numbered-databases/images/zadd-move.drawio.png similarity index 100% rename from content/blog/2025-09-10-numbered-databases/images/zadd-move.drawio.png rename to content/blog/2025-09-25-numbered-databases/images/zadd-move.drawio.png diff --git a/content/blog/2025-09-10-numbered-databases/index.md b/content/blog/2025-09-25-numbered-databases/index.md similarity index 88% rename from content/blog/2025-09-10-numbered-databases/index.md rename to content/blog/2025-09-25-numbered-databases/index.md index ac7f30a9..5b5d6a30 100644 --- a/content/blog/2025-09-10-numbered-databases/index.md +++ b/content/blog/2025-09-25-numbered-databases/index.md @@ -1,7 +1,7 @@ +++ -title= "Numbered “Databases” in Valkey 9.0" +title= "Numbered Databases in Valkey 9.0" description = "Valkey 9.0 brings new namespacing abilities to cluster mode. In this blog you'll learn about numbered databases, how they've changed in the recent release, limitations, and how you can use them to efficiently solve a variety of otherwise challenging problems." -date= 2025-09-10 00:00:00 +date= 2025-09-25 00:00:00 authors= [ "kyledvs"] [extra] @@ -10,7 +10,7 @@ featured_image = "/blog/numbered-databases/images/move-db.drawio.png" +++ -If you explore Valkey’s documentation you might run across a feature called ‘numbered databases’ which allows you to separate the keyspace into (by default) 16 different databases. Digging into this feature reveals tantalizing ways to avoid key prefixing, house different workloads together on Valkey, and even perform patterns that are otherwise clunky. However, if you’ve done more research outside of the documentation on numbered databases you might run across a advice like “don’t use them,” “they don’t scale,” and “they’re a bad idea.” Well, the forthcoming Valkey 9.0 changes many things with numbered databases and you’ll see in this post that advice definitely needs some updating. +If you explore Valkey’s documentation you might run across a feature called ‘numbered databases’ which allows you to separate the keyspace into (by default) 16 different databases. Digging into this feature reveals tantalizing ways to avoid key prefixing, house different workloads together on Valkey, and even perform patterns that are otherwise clunky. However, if you’ve done more research outside of the documentation on numbered databases you find advice like “don’t use them,” “they don’t scale,” and “they’re a bad idea.” Well, the forthcoming Valkey 9.0 changes many things with numbered databases and you’ll see in this post that advice definitely needs some updating. Today, a common way to conceptualize Valkey is that your keys represent a unique name for pointers to data in memory across a cluster of nodes. So, key `foo` is unique and deterministically linked to a specific node and on that node there is a memory address where the value resides. However, this misses one important detail: the database number. The reality is that key names belong to a specific numbered database and *aren’t unique* on a given instance of Valkey. To put this another way, Valkey can have the key `foo` as many times as there are numbered databases with each one pointing to different data. @@ -43,11 +43,9 @@ OK Here the key `somekey` was set to two different values: ‘hi’ on database 0, and ‘hello’ on database 5, with `SELECT` altering the selected database. `CLUSTER KEYSLOT` was called twice: each one yielding the same slot number meaning this key will be assigned to the same node in the cluster, no matter which database is selected. -## What are numbered databases and limits +## Limitations -If you take away one thing from this blog it should be this: **numbered databases are a form of namespacing**. Consequently, they do not provide any form of resource isolation. It's tempting to point a bunch of applications to a single Valkey cluster with each application taking it's own database. While this certainly *can* work, it works without resource isolation and this setup can suffer from classic noisy neighbour problems: busy applications will affect the others using the same cluster. If you're worried about resource sharing, most of the time you'll be better off just having distinct clusters for each application instead of numbered databases. - -Likewise, numbered databases also do not change the properties of how a Valkey cluster works. The keyspace of each database is still split amongst all the nodes. As a consequence, operations that need to span the entire keyspace will to be run on each node: +Numbered databases do not change the properties of how a Valkey cluster works. The keyspace of each database is still split amongst all the nodes. As a consequence, operations that need to span the entire keyspace will to be run on each node: * [`FLUSHDB`](https://valkey.io/commands/flushdb/) will flush the keys in the current database *on the connected node* * [`SCAN`](https://valkey.io/commands/scan/) will iteratively return keys in the current database *on the connected node.* @@ -55,8 +53,12 @@ Likewise, numbered databases also do not change the properties of how a Valkey c You get the picture: if a command previously said it did something for the entire database, in cluster mode it really means for the connected node’s portion of the database. These are especially important to understand if you're planning to move an application built for non-clustered, numbered databases to a cluster. +Additionally, numbered databases do not provide any form of resource isolation. It's tempting to point a bunch of applications to a single Valkey cluster with each application taking its own database. While this certainly *can* work, it works without resource isolation and this setup can suffer from classic noisy neighbour problems: busy applications will affect the others using the same cluster. If you're worried about resource sharing, most of the time you'll be better off just having distinct clusters for each application instead of numbered databases. + ## Where to use numbered databases +If you take away one thing from this blog it should be this: **numbered databases are a form of namespacing**. + The most straight forward use case of numbered databases is when you need to separate your data logically and you can tolerate the effects of resource sharing (see above). This might be something like keeping customer data separated from one another or combining applications on to a single cluster when resources are unlikely to be an issue. In a similar manner, multiple databases are a useful debugging tool. When you’re building an application it can be difficult to see what happens inside Valkey when you make a change. If you have multiple databases you can run your original code on one database and the changed version on a different database then you can more easily see changes in how data looks in Valkey by just the connection swapping between databases. This is also a useful pattern during a migration when you want your old data to stick around while your new data is populated. An entirely different use of numbered databases is related to the [`MOVE`](https://valkey.io/commands/move/) command. `MOVE` allows you to change a key from one database to another *without copying the data,* meaning it uses very little resources and it’s an `O(1)` operation. This allows a couple of things: 1) you can effectively make data inaccessible from a database whilst keeping it on the same cluster node, and 2) you can replace a complex key atomically. @@ -83,7 +85,7 @@ Aside from the aforementioned lack of resource isolation, numbered databases in Finally, while numbered databases are well supported in client libraries there are rough edges: * Some client libraries artificially restrict usage to a single database in cluster mode, -* Pooled clients may naively manage the selected database, so a client returned to the pool after running `SELECT` might retain the database number in subsequent usage. A similar situation is possible for multiplexed clients. +* Pooled clients may naïvely manage the selected database, so a client returned to the pool after running `SELECT` might retain the database number in subsequent usage. A similar situation is possible for multiplexed clients. In general, watch out for three assumptions: 1) the selected database is always 0, 2) their is only one database in cluster mode, and 3) if there is multiple databases in use it isn’t in cluster mode. None of these are true in Valkey 9.0. From 637a6e91e0392b7e8fc93db047468facff4bac99 Mon Sep 17 00:00:00 2001 From: "Kyle J. Davis" Date: Thu, 25 Sep 2025 07:33:15 -0600 Subject: [PATCH 13/13] Update content/blog/2025-09-25-numbered-databases/index.md Co-authored-by: Ran Shidlansik Signed-off-by: Kyle J. Davis --- content/blog/2025-09-25-numbered-databases/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/blog/2025-09-25-numbered-databases/index.md b/content/blog/2025-09-25-numbered-databases/index.md index 5b5d6a30..e4be79e8 100644 --- a/content/blog/2025-09-25-numbered-databases/index.md +++ b/content/blog/2025-09-25-numbered-databases/index.md @@ -87,6 +87,6 @@ Finally, while numbered databases are well supported in client libraries there a * Some client libraries artificially restrict usage to a single database in cluster mode, * Pooled clients may naïvely manage the selected database, so a client returned to the pool after running `SELECT` might retain the database number in subsequent usage. A similar situation is possible for multiplexed clients. -In general, watch out for three assumptions: 1) the selected database is always 0, 2) their is only one database in cluster mode, and 3) if there is multiple databases in use it isn’t in cluster mode. None of these are true in Valkey 9.0. +In general, watch out for three assumptions: 1) the selected database is always 0, 2) there is only one database in cluster mode, and 3) if there are multiple databases in use it isn’t in cluster mode. None of these are true in Valkey 9.0. With this in mind, Valkey 9.0 gives you the ability to divvy up that keyspace into nice neat numbered databases and spread them out over a whatever cluster you have. So, get rid of that old, outdated advice and start using them, seeing how they scale, and what a good idea number databases actually are for Valkey 9.0.