forgekv.com — A Redis-compatible key-value server built in Rust, designed from the ground up for multi-core scale-out and SSD-backed persistence. Drop-in replacement for Redis — any Redis client works without changes.
docker pull forgekv/forgekvRedis is single-threaded by design. It saturates one core and tops out around 80–90K ops/sec regardless of how many cores your machine has.
ForgeKV uses a 256-shard lock architecture — each shard has its own WAL, memtable, and RwLock. Concurrent writers never block each other unless they hash to the same shard. The result: throughput scales with the number of client threads.
Setup: memtier_benchmark, --network host, pipeline=16, 64-byte values, 20s per config.
t = benchmark threads, c = clients per thread.
| Config | ForgeKV v2 | Redis 7 | Dragonfly | vs Redis | vs Dragonfly |
|---|---|---|---|---|---|
| t=1 c=10 | 452,721 | 451,023 | 144,726 | 100% | 313% |
| t=1 c=20 | 476,677 | 527,199 | 207,407 | 90% | 230% |
| t=2 c=10 | 908,408 | 693,045 | 354,091 | 131% | 257% |
| t=2 c=20 | 955,010 | 756,600 | 408,084 | 126% | 234% |
| t=4 c=10 | 1,542,005 | 525,048 | 592,571 | 294% | 260% |
| t=4 c=50 | 1,452,569 | 618,241 | 760,924 | 235% | 191% |
| Config | ForgeKV v2 | Redis 7 | Dragonfly | vs Redis | vs Dragonfly |
|---|---|---|---|---|---|
| t=1 c=10 | 524,635 | 762,926 | 133,016 | 69% | 394% |
| t=1 c=20 | 570,173 | 730,880 | 232,198 | 78% | 246% |
| t=2 c=10 | 1,108,087 | 736,096 | 381,827 | 150% | 290% |
| t=2 c=20 | 1,226,648 | 837,285 | 484,340 | 147% | 253% |
| t=4 c=10 | 1,962,310 | 548,393 | 668,289 | 358% | 294% |
| t=4 c=50 | 1,171,594 | 627,456 | 887,687 | 187% | 132% |
| Config | ForgeKV v2 | Redis 7 | Dragonfly |
|---|---|---|---|
| t=1 c=10 | 0.343 | 0.303 | 0.703 |
| t=1 c=20 | 0.663 | 0.567 | 1.263 |
| t=2 c=10 | 0.367 | 0.503 | 0.911 |
| t=2 c=20 | 0.727 | 0.863 | 1.767 |
| t=4 c=10 | 0.439 | 1.295 | 1.295 |
| t=4 c=50 | 2.271 | 5.311 | 4.127 |
| Config | ForgeKV v2 | Redis 7 | Dragonfly |
|---|---|---|---|
| t=1 c=10 | 0.84 | 0.61 | 4.13 |
| t=1 c=20 | 1.23 | 1.01 | 4.70 |
| t=2 c=10 | 1.06 | 0.82 | 6.27 |
| t=2 c=20 | 1.50 | 1.53 | 9.02 |
| t=4 c=10 | 1.14 | 2.43 | 10.43 |
| t=4 c=50 | 4.77 | 9.22 | 28.03 |
vs Redis / vs Dragonfly= ForgeKV ÷ competitor × 100%. For throughput: above 100% = ForgeKV wins. For latency: below 100% = ForgeKV wins.
- 256-shard architecture (was 64) — reduced lock contention at high concurrency
- Eliminated redundant metadata reads —
save_meta_innerno longer re-reads from storage; newget_live_meta_innerreplaces the double-lookup pattern across 70+ call sites - Batched writes for LPUSH/RPUSH/HSET/SADD — single WAL+memtable lock acquisition instead of N separate locks per element
- SET single-thread (t=1): ForgeKV matches Redis 7 within 10% and is 2.3–3.1x faster than Dragonfly.
- SET multi-thread (t=4 c=10): 1.54M SET/s — 2.9x Redis 7, 2.6x Dragonfly.
- GET multi-thread (t=4 c=10): 1.96M GET/s — 3.6x Redis 7, 2.9x Dragonfly.
- High concurrency (t=4 c=50): 1.45M SET/s and 1.17M GET/s — both faster than Redis 7 and Dragonfly. In v1 this config was the weak point (73% of Redis SET); now it's a strength.
- Tail latency: SET p99 at t=4 c=50 is 4.8ms — 1.9x better than Redis 7 (9.2ms), 5.9x better than Dragonfly (28.0ms).
Click to expand v1 results
Setup: memtier_benchmark, pipeline=16, 64-byte values, 20s per config.
| Config | ForgeKV v1 | Redis 7 | Dragonfly | vs Redis | vs Dragonfly |
|---|---|---|---|---|---|
| t=1 c=10 | 69,143 | 80,704 | 23,067 | 86% | 300% |
| t=1 c=20 | 76,868 | 85,538 | 26,398 | 90% | 291% |
| t=2 c=10 | 147,992 | 96,279 | 39,477 | 154% | 375% |
| t=2 c=20 | 157,968 | 111,827 | 45,129 | 141% | 350% |
| t=4 c=10 | 100,175 | 61,171 | 61,384 | 164% | 163% |
| t=4 c=50 | 59,401 | 81,660 | 94,665 | 73% | 63% |
| Config | ForgeKV v1 | Redis 7 | Dragonfly |
|---|---|---|---|
| t=1 c=10 | 0.85 | 0.84 | 5.18 |
| t=1 c=20 | 1.59 | 1.38 | 6.24 |
| t=2 c=10 | 1.09 | 1.02 | 4.80 |
| t=2 c=20 | 2.67 | 2.19 | 7.84 |
| t=4 c=10 | 2.90 | 2.67 | 7.10 |
| t=4 c=50 | 17.28 | 11.97 | 27.77 |
Client connections (Tokio async, 1 task per connection)
│
▼
Command Registry
│
▼
RedisDatabase ─── 256 FNV-1a shards (RwLock each)
│
▼
LsmStorage ─── 256-shard WAL + 256-shard MemTable (BTreeMap)
│ │
▼ ▼
SSTable files (SSD) Immutable snapshots → flush
- 256-shard WAL: Each shard writes to its own WAL file with a 256KB BufWriter. WAL rotation is atomic — the WAL lock is held during both rotation and memtable snapshot.
- put2 / put_batch:
SETwrites two entries (meta + data) in a single lock.LPUSH,HSET,SADDbatch all elements + meta into oneput_batchcall — single WAL+memtable lock acquisition regardless of element count. - Redis key-aware sharding:
shard_of()strips the internal storage prefix before hashing, so meta and data keys for the same Redis key always land in the same shard. - Zero redundant reads:
get_live_meta_innercombines existence check + metadata fetch in a single storage read, eliminating the double-lookup pattern across all commands. - Blocking commands:
BLPOP,BRPOP,BLMOVE,BZPOPMIN/MAXuse a Tokio broadcast channel per(db, key).
Full RESP2 protocol. Supported command families:
| Family | Commands |
|---|---|
| Strings | GET, SET, MGET, MSET, INCR/DECR, APPEND, GETRANGE, SETRANGE, GETSET, GETDEL, GETEX, SETNX, SETEX, PSETEX, MSETNX, SUBSTR, LCS |
| Keys | DEL, EXISTS, EXPIRE, PEXPIRE, EXPIREAT, PEXPIREAT, TTL, PTTL, PERSIST, TYPE, RENAME, RENAMENX, COPY, UNLINK, SCAN, KEYS, RANDOMKEY, OBJECT, WAIT |
| Hashes | HGET, HSET, HMGET, HMSET, HDEL, HEXISTS, HGETALL, HKEYS, HVALS, HLEN, HINCRBY, HINCRBYFLOAT, HSCAN, HRANDFIELD, HEXPIRE, HPEXPIRE, HTTL, HPTTL |
| Lists | LPUSH, RPUSH, LPOP, RPOP, LLEN, LRANGE, LINDEX, LSET, LINSERT, LREM, LTRIM, LMOVE, LMPOP, BLPOP, BRPOP, BLMOVE, LPOS |
| Sets | SADD, SREM, SMEMBERS, SISMEMBER, SMISMEMBER, SCARD, SPOP, SRANDMEMBER, SUNION, SINTER, SDIFF, SUNIONSTORE, SINTERSTORE, SDIFFSTORE, SINTERCARD, SSCAN, SMOVE |
| Sorted Sets | ZADD, ZREM, ZSCORE, ZRANK, ZREVRANK, ZRANGE, ZRANGEBYSCORE, ZREVRANGEBYSCORE, ZRANGEBYLEX, ZRANGESTORE, ZCOUNT, ZLEXCOUNT, ZCARD, ZINCRBY, ZPOPMIN, ZPOPMAX, ZRANDMEMBER, ZMPOP, BZPOPMIN, BZPOPMAX, ZDIFF, ZINTER, ZUNION, ZDIFFSTORE, ZINTERSTORE, ZUNIONSTORE, ZMSCORE, ZSCAN |
| HyperLogLog | PFADD, PFCOUNT, PFMERGE |
| Geo | GEOADD, GEODIST, GEOPOS, GEOSEARCH, GEOSEARCHSTORE, GEORADIUS, GEORADIUSBYMEMBER, GEOHASH |
| Bitmaps | SETBIT, GETBIT, BITCOUNT, BITPOS, BITOP, BITFIELD, BITFIELD_RO |
| Pub/Sub | SUBSCRIBE, UNSUBSCRIBE, PUBLISH, PSUBSCRIBE, PUNSUBSCRIBE, PUBSUB |
| Streams | XADD, XREAD, XLEN, XRANGE, XREVRANGE, XGROUP, XREADGROUP, XACK, XCLAIM, XAUTOCLAIM, XDEL, XTRIM, XINFO, XPENDING, XSETID |
| Transactions | MULTI, EXEC, DISCARD, WATCH, UNWATCH |
| Scripting | EVAL, EVALSHA, SCRIPT LOAD/EXISTS/FLUSH |
| Server | INFO, CONFIG GET/SET/REWRITE, DBSIZE, FLUSHDB, FLUSHALL, SELECT, PING, ECHO, QUIT, RESET, DEBUG, COMMAND, LATENCY, SLOWLOG, ACL, CLIENT, TIME, LASTSAVE, BGSAVE, BGREWRITEAOF, SAVE, OBJECT ENCODING/FREQ/HELP/IDLETIME/REFCOUNT/VERSION |
| Modules | JSON (JSON.), Bloom Filter (BF.), RedisSearch stubs (FT.*), CMS/TopK/TDigest |
docker compose upConnects on localhost:6379. Use any Redis client:
redis-cli -p 6379 set foo bar
redis-cli -p 6379 get fooEdit forgekv.conf:
bind 0.0.0.0
port 6379
dir /data
databases 16
cd rust
cargo build --release
./target/release/forgekv --config ../forgekv.confRequires Rust 1.75+.
Reproduce the numbers above (requires Docker):
bash benchmark/redis-comparison/run.shOptions:
--skip-build Skip Docker image rebuild
--test-time=N Seconds per config (default: 20)
Results are saved to benchmark/redis-comparison/results/.
Source-available. Free to use, fork, and self-host for evaluation and non-commercial purposes.
Commercial use, redistribution as a service (SaaS/hosted), or inclusion in commercial products requires a separate commercial license. Visit forgekv.com for licensing inquiries.
The license terms may be updated in future versions.