Redis protocol server, written in Rust · v0.4.0

One process instead of a cache, a lock service and a delay queue.

Ruvio speaks RESP, so redis-cli and your existing clients connect. Each shard owns its keys: no lock on the hot path, and the durability you choose at startup.

Terminal
$ docker run -d -p 6379:6379 \
    -e RUVIO_REQUIREPASS=change-me \
    salihcantekin/ruvio:linux
$ redis-cli -a change-me
6379> LEASE job:nightly 30000
(integer) 1
6379> LIMIT api:key:42 100 60000
(integer) 99

In motion

A node drops off and the cluster keeps going

The coordinator promotes a replica by majority vote and clients follow the new primary on their own. The scenes below play one after another: slot moves, locks, caches and rate limits.

Cluster and failover

Performance

Faster than Redis on the commands you run every day

Each bar is one command measured against Redis 8.10.2 on the same machine. Bars outside the dashed ring are faster than Redis; bars inside it are slower.

1.46×geometric mean throughput across 60 commands
59/60commands at 0.97× of Redis or faster
−25%memory across 12 data shapes, 12 of 12 below Redis
299commands, each with a typed method in 6 clients
MSET (3 keys): 2.52×GEOSEARCH (radius 50 km, COUNT 10): 2.47×SETEX: 2.38×GEOADD: 2.26×COPY ... REPLACE (64 B string): 2.11×GETEX (set a 100 s deadline): 2.00×LMOVE (rotate a 100-element list): 1.85×EXPIRE (key with TTL): 1.71×SETRANGE: 1.68×HGET (10-field hash): 1.68×HSET (10-field hash, existing field): 1.68×SETBIT (1 KiB bitmap, same bit): 1.65×BITFIELD GET u8: 1.61×BITFIELD INCRBY u8 (always writes): 1.60×LINSERT (pivot missing, scans 100): 1.59×LREM (value missing, scans 100): 1.57×LPOS (100 elements, hit in the middle): 1.57×ZADD (existing member, same score): 1.57×HSTRLEN: 1.56×GETBIT (1 KiB bitmap): 1.52×SET: 1.52×HDEL (10-field hash, missing field): 1.52×HSET (existing field): 1.50×LSET (20-item list): 1.50×GETRANGE: 1.48×HGET: 1.48×MEMORY USAGE: 1.48×SISMEMBER: 1.48×LINDEX (20-item list): 1.43×PFADD: 1.42×DUMP (64 B string): 1.42×OBJECT ENCODING: 1.41×BITCOUNT (1 KiB bitmap): 1.38×SADD (existing member): 1.38×EXPIRETIME: 1.37×LLEN: 1.36×RENAME (same key): 1.36×DEL (missing key): 1.35×TOUCH: 1.33×LPUSH: 1.32×EXISTS: 1.32×TTL: 1.32×PERSIST (key without TTL): 1.32×PUBLISH (no subscribers): 1.32×ZINCRBY: 1.32×HMGET (2 fields): 1.29×GET: 1.28×PTTL: 1.27×APPEND (1 byte): 1.27×MGET (3 keys): 1.26×ZSCORE: 1.25×LSET (100 elements): 1.24×PFCOUNT: 1.21×INCRBYFLOAT: 1.18×TYPE: 1.18×SRANDMEMBER: 1.17×LRANGE 0 2: 1.14×LRANGE 0 9 (20-item list): 1.01×HGETALL (10-field hash): 1.00×FILLGET (value present): 0.94×0.8×Redis 1×1.5×2×2.5×1.46×geometric mean vs Redis

Each bar is one command against Redis. See every command, memory and the whole-machine results.

Source: benchmark/records/mac-2026-10-28.json · Apple silicon, 12 cores, 24 GiB, macOS 26.7.1 arm64 · 50 clients, pipeline 16 · in-memory profile, 1 shard · all results

Durability

Choose how much you can afford to lose

Pick a profile at startup. A write is checked, appended, then applied; if the log cannot take the record, the key stays as it was and later writes are refused.

Recovery guarantees
alwaysfdatasync before the reply

Only a write that was never acknowledged (a torn final record).

everysecsync_interval_ms = 1000

Writes the kernel accepted but had not synced yet.

snapshotsnapshot_interval_ms = 60000

Writes after the last durable checkpoint.

memoryno disk writes

All in-memory state when the process stops.

Bounds from docs/RECOVERY.md; intervals are the defaults in ruvio.example.toml.

Compatibility

Your Redis client already works. Six have typed methods.

299 commands in 21 families, with cluster routing from one seed address in every first-party client.

Command reference

Run it next to your app in a minute

One binary or one container. Your Redis client already knows how to talk to it.