Single node Valkey in mostly memory safe Rust. Verified against Valkey's test suite, uses memory safe TLS with rustls.
Live benchmarks & coverage → valdr.dev
Valdr is a port of Valkey aiming to be fully compatible with Redis/Valkey clients in memory safe Rust. The motivation for this project is to attempt to build mostly memory safe alternatives to core web infrastructure and to explore architecture choices that will enable faster performance in the long run.
This repo heavily leveraged coding agents in the process. This was largely inspired by the changing landscape of memory safety attacks as agentic cyber capabilities increase.
Warning
Alpha. Single-node core test suite is green and able to run real loads over TLS. This project is still in alpha.
Performance
Server config: no .conf file — both servers are launched from explicit flags by the bench harness, persistence off, otherwise stock defaults.
Per-command (default valkey-benchmark suite)
| Command | Valdr rps | Valkey 9.1.0 (jemalloc) rps | Ratio |
|---|---|---|---|
| PING_INLINE | 6,666,667 | 4,761,905 | 1.400× |
| PING_MBULK | 9,090,909 | 6,250,000 | 1.455× |
| SET | 4,166,667 | 2,941,176 | 1.417× |
| GET | 5,000,000 | 3,846,154 | 1.300× |
| INCR | 4,545,454 | 4,000,000 | 1.136× |
| LPUSH | 2,702,703 | 2,702,703 | 1.000× |
| RPUSH | 2,702,703 | 3,030,303 | 0.892× |
| LPOP | 2,777,778 | 2,500,000 | 1.111× |
| RPOP | 2,564,102 | 2,702,703 | 0.949× |
| SADD | 3,448,276 | 3,571,428 | 0.966× |
| HSET | 2,777,778 | 2,777,778 | 1.000× |
| SPOP | 4,761,905 | 4,347,826 | 1.095× |
| ZADD | 2,631,579 | 2,380,952 | 1.105× |
| ZPOPMIN | 4,347,826 | 4,000,000 | 1.087× |
| LRANGE_100 | 185,529 | 132,979 | 1.395× |
| LRANGE_300 | 59,277 | 39,620 | 1.496× |
| LRANGE_500 | 35,398 | 22,878 | 1.547× |
| LRANGE_600 | 30,340 | 18,713 | 1.621× |
| MSET | 699,301 | 515,464 | 1.357× |
| MGET | 1,075,269 | 793,651 | 1.355× |
| XADD | 1,388,889 | 1,724,138 | 0.806× |
| FCALL | 1,030,928 | 1,449,275 | 0.711× |
- Wins (ratio ≥ 1.2×):
ping_inline,ping_mbulk,set,get,lrange_100,lrange_300,lrange_500,lrange_600,mset,mget. - Parity (0.95×–1.2×):
incr,lpush,lpop,sadd,hset,spop,zadd,zpopmin. - Behind (< 0.95×):
rpush,rpop,xadd,fcall
Pipeline-depth curve (GET/SET/PING/INCR at p=1/16/100)
| Workload | Valdr rps | Valkey 9.1.0 (jemalloc) rps | Ratio |
|---|---|---|---|
| GET p=1 | 162,866 | 147,059 | 1.107× |
| GET p=16 | 2,597,402 | 2,040,816 | 1.273× |
| GET p=100 | 4,761,905 | 3,571,428 | 1.333× |
| PING p=1 | 179,211 | 159,236 | 1.125× |
| PING p=16 | 2,816,901 | 2,469,136 | 1.141× |
| PING p=100 | 8,000,000 | 5,882,352 | 1.360× |
| SET p=1 | 177,936 | 154,799 | 1.149× |
| SET p=16 | 1,980,198 | 1,785,714 | 1.109× |
| SET p=100 | 4,081,633 | 2,816,901 | 1.449× |
| INCR p=1 | 207,469 | 174,825 | 1.187× |
| INCR p=16 | 2,173,913 | 2,325,581 | 0.935× |
| INCR p=100 | 4,166,667 | 3,448,276 | 1.208× |
How the numbers are produced
- Warmup: 1,000
PING_MBULKrequests (1 client, pipeline 1) before every measured row. - Refresh:
make bench-release(fresh local artifacts) thenmake site-data, which regeneratesdocs/perf-data.json,docs/perf.svg,docs/perf.png, and rewrites the table above from it. The valdr.dev landing page fetches the same JSON, so the site and this README can never disagree — they share one source of truth. - Switch the Valkey adversary:
git -C reference/valkey checkout <tag> && make -j MALLOC=jemalloc BUILD_TLS=no, then re-run the refresh.
Coverage
Valkey's own test suite full breakdown by category → valdr.dev/coverage.html.
Counted assertions (54-file run) [████████████████████] 100.0% 3,035 / 3,035
Single-node core blocks [████████████████████] 99.96% 2,525 / 2,526
Full upstream suite [███████████░░░░░░░░░] 59% 2,534 / 4,281
The only unproven single-node core source block is unit/replybufsize.tcl, which
the current tag policy filters to a 0/0 run. The full-suite figure is lower
because ~41% of upstream tests cover surfaces valdr does not claim yet: cluster,
modules, Sentinel, HA replication, and platform-specific integration.
Status
| Area | Status |
|---|---|
| Release state | Alpha |
| Primary target | Single-node Redis/Valkey workloads |
| Protocol | RESP2 / RESP3 |
| Client compatibility | Existing Redis clients |
| License | BSD-3-Clause |
Compatibility
| Surface | Current state | Evidence |
|---|---|---|
| Single-node RESP wire behavior | Full on current smoke corpus | 23 / 23 byte-exact scripts vs upstream Valkey |
| RDB load/save interop | Full on current corpus | 378 / 378 bidirectional checks |
| Upstream TCL suite | Single-node core green; not a full-suite claim | 3,035 / 3,035 counted assertions in the 54-file wrapper; full denominator 4,281 source blocks bucketed at valdr.dev/coverage.html |
| Cluster mode | Not implemented | Out of scope for current alpha |
| Loadable C modules | Not implemented | Out of scope for current alpha |
| Production HA / Sentinel | Not claimed | Replication remains alpha; PSYNC/HA behavior is outside the single-node alpha promise. AOF is single-node correctness-gated, with performance/durability wording limited to measured telemetry. |
| In-process TLS | Enabled (rustls; no OpenSSL) | TLS 1.2 + 1.3; mTLS tri-state (no/optional/yes); dynamic CONFIG SET of tls-protocols, tls-auth-clients, cert/key paths. CBC-suite tests in unit/tls.tcl are a deliberate rustls divergence. |
Features
| Feature | Status |
|---|---|
| Strings | Implemented |
| Lists | Implemented |
| Hashes | Implemented |
| Sets | Implemented |
| Sorted sets | Implemented |
| Streams | Implemented |
| Pub/sub | Implemented |
| Transactions | Implemented |
| Lua scripting | Implemented |
| ACL / AUTH | Implemented |
| Multi-DB | Implemented |
| Expiration / TTL | Implemented |
| Maxmemory eviction | Implemented |
| RDB persistence | Implemented and oracle-gated |
| AOF | Single-node alpha, correctness-gated |
| Replication | Alpha |
| RedisJSON-compatible commands | Native subset |
| RedisBloom-compatible commands | Native subset |
Run
cargo build --release ./target/release/redis-server --port 6379 --bind 127.0.0.1
Docker
docker pull ghcr.io/ianm199/valdr:alpha docker run --rm -p 6379:6379 ghcr.io/ianm199/valdr:alpha
Benchmark Commands
A rough, runnable head-to-head against the official
valkey/valkey:8-alpineimage (both sides ship jemalloc). Benchmarking inside a container is noisy — especially Docker Desktop on macOS, where per-run throughput can swing ~2×. The Performance chart above is the measurement of record: native binaries, warmed, jemalloc on both sides, vs Valkey 9.1.0. For a stable head-to-head, run this on a Linux host.
Run official valkey-benchmark against Valkey and valdr Docker images
docker network create valdr-bench docker run -d --rm \ --name valkey-ref \ --network valdr-bench \ valkey/valkey:8-alpine docker run -d --rm \ --name valdr \ --network valdr-bench \ ghcr.io/ianm199/valdr:alpha sleep 1
docker run --rm \
--network valdr-bench \
valkey/valkey:8-alpine \
valkey-benchmark \
-h valkey-ref \
-p 6379 \
-n 100000 \
-c 50 \
-P 100 \
-d 64 \
-t ping_inline,ping_mbulk,set,get,incr,lpush,rpush,lpop,rpop,sadd,hset,spop,zadd,zpopmin,lrange_100,lrange_300,lrange_500,lrange_600,mset,mget,xadd,function_load,fcall \
--csv \
--precision 3docker run --rm \
--network valdr-bench \
valkey/valkey:8-alpine \
valkey-benchmark \
-h valdr \
-p 6379 \
-n 100000 \
-c 50 \
-P 100 \
-d 64 \
-t ping_inline,ping_mbulk,set,get,incr,lpush,rpush,lpop,rpop,sadd,hset,spop,zadd,zpopmin,lrange_100,lrange_300,lrange_500,lrange_600,mset,mget,xadd,function_load,fcall \
--csv \
--precision 3docker rm -f valkey-ref valdr docker network rm valdr-bench
Test Commands
bash scripts/setup-reference.sh
cargo build -p redis-server
cargo test --workspace
bash harness/oracle/smoke.sh --skip-build
python3 harness/oracle/rdb-diff --direction=all
bash harness/oracle/run-single-node-tcl-suite.sh --skip-build
bash harness/bench/official-warm-run.shThe single source of truth for what these prove — counted TCL passes, single-node source-block coverage, and how the full 4,281-block upstream denominator is bucketed — is valdr.dev/coverage.html.



























