
KeyDB was born with a simple promise: take Redis, which executes commands on a single thread, and make it use all the cores on the machine. It worked, became a product, was acquired by Snap, and gained features Redis never had, such as active replication between two masters and member expiration within a set. The catch is that in September 2026 the latest KeyDB version is almost three years old. Before putting KeyDB into production, it's worth knowing what it does well, what breaks, and where the project stands. This post installs, configures, replicates, and benchmarks KeyDB in containers, and ends with a recommendation.
Where KeyDB came from
KeyDB started in early 2019 as an experiment by John Sully and Ben Schermel, in Toronto, to add multithreading to Redis. The project grew, went through Y Combinator (2020 summer batch) and became EQ Alpha Technology, which maintained two editions: the open one and KeyDB Pro, closed and paid.
In 12 May 2022 KeyDB announced that it became part of Snap, owner of Snapchat. With the acquisition, the code from the Pro edition was opened and version 6.3.0 merged everything into a single project under the BSD-3-Clause. license. The repository moved from EQ-Alpha/KeyDB to Snapchat/KeyDB, and Snap began using KeyDB in part of its own cache layer.
The stated reason for the fork is in the README: the authors felt that Redis prioritized code simplicity over simplicity for the user, who ended up needing external components (Sentinel, proxies, scripts) to solve common problems. KeyDB wanted to be Redis “with batteries included”, maintaining compatibility with the protocol, modules, and Lua scripts.
How the multithreaded architecture works
The classic Redis executes all commands on a main thread. Since version 6 it can use io-threads to read and write to sockets in parallel, but command execution remains serialized. KeyDB went another way: it runs the entire event loop on multiple threads. Each connection is assigned to a thread on accept(), and parsing and network I/O happen in parallel. Access to the key table is protected by a spinlock, and transactions hold that lock for the entire duration of the EXEC, which preserves the atomicity that applications expect from Redis (the authors' explanation).
In practice, this is controlled by two directives in the keydb.conf:
server-threads 4 # threads que atendem clientes (padrão do pacote: 2)
server-thread-affinity true # fixa cada thread num núcleo
The README recommends relating server-threads to the number of NIC queues, not to the number of cores, and suggests 4 as a starting point: because KeyDB uses spinlocks, too many threads increase lock contention. In the benchmark below, 8 threads still performed better than 4 with 6 cores dedicated to the server, so measure on your own hardware.
The diagram shows the two nodes used in this post's lab, each with four threads, and active replication between them:

Features Redis does not have
According to Oracle's official documentation, KeyDB adds to Redis' feature set:
- Active replication: two or more nodes are replicas of each other and accept reads and writes at the same time. There is no replica promotion or Sentinel on failover; just a TCP load balancer pointing to the healthy nodes. With multiple nodes in a mesh, the feature becomes multi-master. The documentation promises that, after a network partition, “the newer write wins” (last write wins). In the tests below, that did not happen.
- Subkey expires: the command
EXPIREMEMBERgives a TTL to a member of a set, hash, or sorted set, not to the entire key. In Redis, this feature only arrived in version 7.4, and only for hash fields. - MVCC: a documentation describes snapshots that allow executing
KEYSandSCANwithout blocking the database, and a background save withoutfork(), which avoids duplicating memory pages during the snapshot. - FLASH storage: with
storage-provider flash /caminho, KeyDB writes everything to a RocksDB on SSD/NVMe and keeps only hot data in RAM. The documentation itself classifies the feature as beta/experimental. - Direct backup to S3 with
db-s3-object, and ModJS, a module for writing commands in JavaScript on top of V8.
The state of the project in September 2026
I consulted the project's GitHub, Docker Hub, and APT repository in 23 September of 2026:
| Indicator | Status |
|---|---|
| Latest release | v6.3.4, published on 30/10/2023 |
Last commit on branch main |
April 2024 (build tweaks) |
Docker image eqalpha/keydb:latest |
6.3.4 from 30/10/2023, Ubuntu base 20.04 |
| APT repository | Ubuntu 20.04/22.04 and Debian 11/12; without Ubuntu 24.04 nor Debian 13 |
| Open issues | 292 |
| Codebase | Redis 6.2 (the server itself advertises as redis_version:6.3.4) |
In 31 of January 2025, John Sully, KeyDB's lead author, posted a farewell issue: it was his last day at Snap, he did not know what the company would do with the project and suggested that development effort move to the Valkey, which, in his tests, had already matched KeyDB's performance. Since then, the issue “Is KeyDB abandoned by Snap Inc?” has remained unanswered by any maintainer.
The most serious piece of data is security-related. The CVE-2025-49844 (CVSS 9.9 no NVD) is a use-after-free in Lua that allows remote code execution by an authenticated user, and according to NVD it affects “all versions of Redis with Lua scripting”. KeyDB inherited this code. The PR that ports the fix has been open since October 2025: it received approvals from community users, but no maintainer merged it.
Honest conclusion: KeyDB is stalled. The repository has not been archived and Snap may continue using an internal version, but the public project receives no releases, security fixes, or packages for current distributions.
Installation on Ubuntu and Debian
The project maintains its own APT repository. I tested the procedure in containers with systemd, and it worked on Ubuntu 22.04 and in the Debian 12:
echo "deb https://download.keydb.dev/open-source-dist $(lsb_release -sc) main" \
| sudo tee /etc/apt/sources.list.d/keydb.list
sudo wget -O /etc/apt/trusted.gpg.d/keydb.gpg \
https://download.keydb.dev/open-source-dist/keyring.gpg
sudo apt update
sudo apt install keydb
sudo systemctl enable --now keydb-server
The package keydb installs the keydb-server (systemd service running as user keydb, configuration in /etc/keydb/keydb.conf) and its keydb-tools (keydb-cli, keydb-benchmark, keydb-check-aof and keydb-check-rdb). To review the service commands, see Mastering systemd.
systemctl is-active keydb-server
# active
keydb-cli ping
# PONG
keydb-cli set curso linuxpro && keydb-cli get curso
# OK
# "linuxpro"
On Ubuntu 24.04 and in the Debian 13, the apt update fails because the repository doesn't have the suites noble and trixie. On Ubuntu 24.04, switch $(lsb_release -sc) by jammy installed and started the service without error in my test. This is a workaround, not official support, and Debian 13 still has no package (there is an issue requesting, with no response).
Running with Docker
The official image is eqalpha/keydb. It brings protected-mode no and no password in keydb.conf default, so never publish the port without setting up authentication. A minimal instance, only on localhost and with a password:
docker run -d --name keydb \
-p 127.0.0.1:6379:6379 \
-v keydb-data:/data \
eqalpha/keydb:x86_64_v6.3.4 \
keydb-server /etc/keydb/keydb.conf \
--requirepass 'TroqueEstaSenha' \
--server-threads 4 \
--appendonly yes
docker exec -it keydb keydb-cli -a 'TroqueEstaSenha' ping
Any Redis client works without change, including the redis-cli and the language libraries, because the protocol is the same. If you don't use containers in your day to day, the history of Docker explains where the tool comes from.
Active replication between two nodes
The lab uses two containers, keydb-lab-a and keydb-lab-b, on a Docker network. Each node points to the other with replicaof and starts active-replica:
# keydb-a.conf (no keydb-b.conf, troque para: replicaof keydb-lab-a 6379)
port 6379
bind 0.0.0.0
protected-mode yes
requirepass SenhaForte123
masterauth SenhaForte123
server-threads 4
active-replica yes
replicaof keydb-lab-b 6379
appendonly yes
dir /data
docker network create keydb-lab-net
for n in a b; do
docker run -d --name keydb-lab-$n --network keydb-lab-net \
-v $PWD/keydb-$n.conf:/etc/keydb/keydb.conf:ro \
eqalpha/keydb:x86_64_v6.3.4 keydb-server /etc/keydb/keydb.conf
done
A="docker exec keydb-lab-a keydb-cli -a SenhaForte123 --no-auth-warning"
B="docker exec keydb-lab-b keydb-cli -a SenhaForte123 --no-auth-warning"
$A info replication | grep -E 'role|link_status'
# role:active-replica
# master_global_link_status:up
# master_link_status:up
$A set site linuxpro.com.br ; $B get site # "linuxpro.com.br"
$B set autor nilton ; $A get autor # "nilton"
The log confirms the four threads (Thread 0 alive up to Thread 3 alive) and the warning that active-replica yes implies replica-read-only no. Writes made on any node appeared on the other in less than a second.
The scenario highlighted in the documentation also worked: with node B stopped, I wrote a new value to A. When I brought B back up, it synchronized and started showing the new value, without overwriting A with the old data from its AOF.
The network partition test
Then I simulated a network partition. I lowered the repl-timeout to 5 seconds, disconnected node B from the Docker network and waited for the master_link_status to move to down. With the nodes isolated, I wrote the same key on both and reconnected B:
$A config set repl-timeout 5 ; $B config set repl-timeout 5
docker network disconnect keydb-lab-net keydb-lab-b
# ... aguarda master_link_status:down em B ...
$B set k6 azul-antigo # escrita mais velha, em B
$A set k6 verde-novo # escrita mais nova, em A (2 s depois)
docker network connect keydb-lab-net keydb-lab-b
# ... aguarda master_link_status:up ...
$A get k6 # "azul-antigo"
$B get k6 # "verde-novo"
Instead of converging to the newest write, the nodes swapped values and ended up diverged. The log showed a partial resynchronization (Successful partial resynchronization), and each node applied the other's write on top. I repeated the test seven times, with partitions ranging from 3 to 15 seconds, both with the replication link going down and without it actually going down, and the result was always the same. The divergence persisted until a docker restart keydb-lab-b forced a full synchronization, and at that point both nodes ended up with azul-antigo: the newest write was lost.
This behavior is known. The issue #366 reports the same problem since September of 2021, and in December of 2023 another user confirmed that it continued in 6.3.4. Since active replication is the main reason to choose KeyDB, this weighs: do not use active-replica where a silent data divergence is unacceptable.
Member expiration with EXPIREMEMBER
This feature worked as documented, including being replicated to the other node:
$A sadd sessoes u1 u2 u3
$A expiremember sessoes u1 3 # u1 expira em 3 s
$A ttl sessoes # -1: a chave em si não expira
sleep 4
$A smembers sessoes # u2, u3
$B smembers sessoes # u2, u3
$A hset carrinho item1 a item2 b
$A expiremember carrinho item1 2000 ms # unidade opcional: s ou ms
For caches with tags or session lists, this avoids the trick of keeping a parallel sorted set just to manage the validity of each member.
Simple benchmark: KeyDB, Valkey, and Redis
KeyDB's README warns that the keydb-benchmark and the redis-benchmark are too slow to saturate a multithreaded server and recommends the memtier_benchmark. That's what I used, in containers on the same machine.
Environment: AMD Ryzen 9 9900X (12 cores/24 threads), 186 GB of RAM, Docker on a bridge network. The server was pinned to 6 physical cores (--cpuset-cpus 0-5,12-17) and memtier to the other 6 (6-11,18-23), without sharing a kernel. No persistence (--save "" --appendonly no), 200 thousand 100-byte keys preloaded, 8 threads × 50 connections in memtier, 1 SETs to 10 GETs, random keys, 20 seconds per round. I ran three rounds per configuration, and the table shows the median. The machine was running other containers at the same time, so compare rows against each other, not against numbers from other environments.
docker run --rm --network keydb-lab-net --cpuset-cpus 6-11,18-23 \
redislabs/memtier_benchmark:latest -s keydb-lab-srv -p 6379 \
--protocol=redis --threads=8 --clients=50 --ratio=1:10 \
--data-size=100 --key-maximum=200000 --key-pattern=R:R \
--test-time=20 --hide-histogram
| Server and configuration | ops/s (median) | average latency | p99 |
|---|---|---|---|
KeyDB 6.3.4, server-threads 1 |
213 thousand | 1,88 ms | 2,78 ms |
Valkey 9.1.2, io-threads 1 |
214 thousand | 1,86 ms | 3,81 ms |
KeyDB 6.3.4, server-threads 4 |
833 thousand | 0,48 ms | 1,01 ms |
Valkey 9.1.2, io-threads 4 |
633 thousand | 0,63 ms | 1,01 ms |
KeyDB 6.3.4, server-threads 8 |
1,30 million | 0,31 ms | 0,81 ms |
Valkey 9.1.2, io-threads 8 |
1,25 million | 0,32 ms | 0,58 ms |
Redis 8.10.2, io-threads 8 |
1,28 million | 0,31 ms | 0,65 ms |
What the numbers show:
- With one thread, KeyDB and Valkey are tied, which makes sense: they are essentially the same engine inherited from Redis.
- With 4 threads, KeyDB is about 30% ahead of Valkey. Running commands across multiple threads still pays off when there are few threads.
- With 8 threads, all three are within 4% of each other, and Valkey and Redis have the lowest p99. At that point, the bottleneck is likely memtier itself or the Docker network stack, no longer the server.
In short, the performance advantage that justified KeyDB in 2019 is now small, and only shows up with few threads. This matches what John Sully himself wrote when leaving Snap.
Redis vs. Valkey vs. KeyDB
Data verified in the official repositories in 23/09/2026:
| Redis | Valkey | KeyDB | |
|---|---|---|---|
| License | tripled since 8.0: RSALv2, SSPLv1 or AGPLv3 (7.4 was only RSALv2/SSPL) | BSD-3-Clause | BSD-3-Clause |
| Who maintains | Redis Ltd. | community, under the Linux Foundation | Snap (no public activity) |
| Latest stable version | 8.10.2 (17/09/2026) | 9.1.2 (01/09/2026) | 6.3.4 (30/10/2023) |
| Codebase | own | fork of the latest BSD Redis (7.2 series) | fork of Redis 6.2 |
| Multithread | I/O threads; commands on a single thread | I/O threads; commands on a single thread | event loop and commands across multiple threads |
| Cluster with sharding | yes | yes | yes (Redis 6.2 cluster mode) |
| Multi-master replication | no in the open source edition | no | yes, with the split-brain bug above |
| Per-member expiration | hash fields (since 7.4) | hash fields (since 9.0) | set, hash, and sorted set |
| Fix for CVE-2025-49844 | yes (8.2.2 and backports) | yes | no |
The Redis license change was announced on 20 de March de 2024. The Linux Foundation launched Valkey in 28 de March de 2024 from the last BSD code, and in 1st of May of 2025 Redis 8 added AGPLv3 as a third option, returning to having an OSI-approved license.
A caution with the comparisons circulating on the internet: there are articles that attribute to KeyDB the Apache license 2.0 (the license is BSD-3-Clause) and performance tables without environment or method described. Always check the repository and measure on your hardware.
Which one to choose
- New project: use Valkey. It is BSD, has frequent releases, security fixes, packages in current distributions, and is the recommended alternative by KeyDB's own author. With
io-threadsit already takes advantage of multiple cores. - Need the Redis Ltd. ecosystem. (integrated Redis 8 modules, commercial support)? Use Redis, knowing the license is AGPLv3 or source-available.
- Already running KeyDB in production? Plan the migration to Valkey. While it does not happen, block Lua scripts for those who do not need them (
ACL SETUSER <usuario> -@scripting, which I tested in 6.3.4), do not expose the port outside the internal network, and treat active replication as subject to divergence.EXPIREMEMBERand active replication do not exist in Valkey, so review the code that uses those features. - KeyDB in a new project: I do not recommend it. The performance that justified it has fallen behind, and the lack of maintenance weighs more.
Conclusion
KeyDB proved a thesis: a Redis-compatible cache could use all cores, and that pressure helped push Redis and Valkey toward I/O multithreading. But a database without a maintainer, without a fix for a critical RCE, and with active replication that loses writes after a partition should not receive new data in 2026. For those who need high availability, the path is Valkey, and the post Valkey in a cluster shows how to set up three primaries and three replicas, with tested failover. If the cache is going into production, monitor it properly, with Prometheus and Node Exporter or with a simple checker like the Go Uptime. And if your Go application already uses Redis for queues, the post about Asynq works the same way with Valkey.