Valdr

Valkey, in safe Rust. Alpha.

Single-node Valkey workalike. Safe-Rust data engine, RESP parser, and TLS stack. No fork(), no C module ABI. The Lua VM still wraps the upstream C interpreter — see MLUA_EXIT_PLAN.md for the path to replace it.

Coverage

  Counted assertions             ██████████  3,015 / 3,015
  Single-node-core blocks        █████████░  2,466 / 2,541   · 97%
  Full upstream Valkey suite     ██████░░░░  2,466 / 4,299   · 57%

The 1,758-block gap to 4,299 is out of scope — cluster, modules, sentinel, replication-integration, platform. Not failing. Verified 2026-05-28 against Valkey 9.1.0; bucketing in docs/TEST_AND_FEATURE_COVERAGE.md.

Scope

  Strings, lists, hashes, sets, sorted sets  ████████████  full
  Streams + consumer groups                  ████████████  full
  Pub/Sub (regular + sharded)                ████████████  full
  Transactions (MULTI/EXEC/WATCH)            ████████████  full
  Scripting (EVAL/EVALSHA/FCALL)             ████████████  via mlua
  ACL, AUTH, multi-DB                        ████████████  full
  Expiration, maxmemory eviction             ████████████  full
  RDB persistence                            ████████████  bidirectional
  TLS                                        ████████████  rustls 1.2/1.3, mTLS

  AOF persistence                            ███████░░░░░  alpha
  Replication                                ██████░░░░░░  alpha · partial-resync unproven

  Cluster mode                               ░░░░░░░░░░░░  not implemented
  Sentinel HA                                ░░░░░░░░░░░░  not implemented
  Loadable C module ABI                      ░░░░░░░░░░░░  not implemented

Performance

  GET    p=1     ░░░░░             0.95× / 0.92×
  GET    p=16    ▒▒▒▒▒▒▒           1.06× / 1.12×
  GET    p=100   █████████         1.32× / 1.53×

  Default-suite median across 23 commands             1.13× / 1.15×

Throughput ratios vs Valkey 8.1.7 / 9.1.0, same host (Apple M3 Max), warmed.

Full per-row data (9 pipeline depths + 23 commands)
vs Valkey 8.1.7
WorkloadValdr rpsValkey rpsRatio
Pipeline-depth · GET / PING_MBULK / SET · p = 1 / 16 / 100
GET p=1 149,925 157,233 0.954×
GET p=16 2,202,6432,083,3331.057×
GET p=100 5,555,5564,201,6801.322×
PING p=1 152,905 160,514 0.953×
PING p=16 2,267,5742,232,1431.016×
PING p=100 7,246,3775,102,0411.420×
SET p=1 150,376 159,236 0.944×
SET p=16 1,941,7481,757,4691.105×
SET p=100 3,610,1082,695,4181.339×
Default suite · pipeline = 100 · payload = 64 bytes
ping_inline 5,263,1583,703,7041.421×
ping_mbulk 7,142,8575,555,5561.286×
set 3,703,7043,030,3031.222×
get 4,761,9053,846,1541.238×
incr 4,166,6674,000,0001.042×
lpush 2,777,7782,439,0241.139×
rpush 2,702,7032,702,7031.000×
lpop 2,564,1022,272,7271.128×
rpop 2,380,9522,500,0000.952×
sadd 2,380,9523,225,8060.738×
hset 1,724,1382,500,0000.690×
spop 2,857,1434,000,0000.714×
zadd 1,923,0772,439,0240.788×
zpopmin 2,857,1434,166,6670.686×
lrange_100 176,367 129,032 1.367×
lrange_300 56,180 38,971 1.442×
lrange_500 34,153 23,175 1.474×
lrange_600 27,778 18,685 1.487×
mset 636,943 456,621 1.395×
mget 1,063,829847,457 1.255×
xadd 1,123,5961,388,8890.809×
function_load 578,035 58,893 9.815×
fcall 847,458 1,428,5710.593×
vs Valkey 9.1.0
WorkloadValdr rpsValkey rpsRatio
Pipeline-depth · GET / PING_MBULK / SET · p = 1 / 16 / 100
GET p=1 161,551 175,747 0.919×
GET p=16 2,590,6742,304,1481.124×
GET p=100 6,024,0963,937,0081.530×
PING p=1 179,533 177,305 1.013×
PING p=16 2,375,2972,331,0021.019×
PING p=100 7,407,4074,950,4951.496×
SET p=1 165,016 176,991 0.932×
SET p=16 2,028,3971,607,7171.262×
SET p=100 3,636,3632,347,4181.549×
Default suite · pipeline = 100 · payload = 64 bytes
ping_inline 5,263,1584,000,0001.316×
ping_mbulk 7,142,8575,555,5561.286×
set 3,846,1542,564,1021.500×
get 4,545,4543,448,2761.318×
incr 3,846,1543,571,4281.077×
lpush 2,564,1022,380,9521.077×
rpush 2,500,0002,777,7780.900×
lpop 2,500,0002,173,9131.150×
rpop 2,380,9522,439,0240.976×
sadd 2,325,5813,125,0000.744×
hset 1,754,3862,500,0000.702×
spop 2,857,1433,703,7040.771×
zadd 1,851,8522,222,2220.833×
zpopmin 2,702,7033,703,7040.730×
lrange_100 186,916 114,943 1.626×
lrange_300 62,461 37,722 1.656×
lrange_500 35,137 21,777 1.613×
lrange_600 29,308 18,123 1.617×
mset 628,931 442,478 1.421×
mget 1,030,928740,741 1.392×
xadd 1,098,9011,408,4510.780×
function_load 588,235 56,593 10.394×
fcall 869,565 1,351,3510.643×

Each adversary measured in its own run; Valdr-rps differs by ~3–8% between runs (normal variance on un-quantized rps numbers).

Try it

docker pull ghcr.io/ianm199/valdr:alpha
docker run -d --name valdr -p 6379:6379 ghcr.io/ianm199/valdr:alpha
printf 'PING\r\n' | nc 127.0.0.1 6379
# +PONG

docker run --rm --network host valkey/valkey:8-alpine \
  valkey-benchmark -h 127.0.0.1 -p 6379 -n 100000 -c 50 -P 100 -t get,set