
Five in-memory engines, one 48-core bare-metal box, one harness, raw data published. This page has all the numbers on it โ throughput, latency, memory, scaling curves, and the caveats that decide whether you should believe any of them. The seven-part series underneath goes deeper on each; the interactive explorer lets you filter the raw runs yourself.
- ๐ Dragonfly, one process: 15.5M ops/s
- ๐ด Redis Cluster, driven by a normal client: 4.6M ops/s
- ๐ด Redis Cluster, driven perfectly: 40.6M ops/s
All three are real, measured on the same machine, on the same workload, within minutes of each other. That spread โ 9ร between how a cluster can perform and how a normal client actually drives it โ turned out to be the most interesting finding in the whole project, and it is the number most benchmarks quietly pick one side of.
๐ฌ Explore the raw runs yourself
Every number on this page is filterable by engine, core count, workload, value size and pipeline depth in the interactive Benchmark Explorer โ 600+ recorded runs, medians computed live, run-health (hit rate, connection errors) shown behind every point. No sign-up, no email. Open the explorer โ
Read this before you quote a number
I would rather you trust a smaller claim than repeat a bigger one I can't defend. So, up front:
- These are two separate capture sessions and I do not mix them. Session 1 (Sep 1) measured Redis, Valkey and Dragonfly with an Intel
c7i.24xlargeload generator. Session 2 (Sep 9) measured KeyDB and Garnet with an AMDc7a.24xlargeload generator, because the Intel client had no capacity in the AZ that evening. A number from Table A and a number from Table B are not directly comparable โ the KeyDB/Garnet write-up shows how far the same-day reference figures moved between the two, which is exactly why I keep the sessions apart. - The "ceiling" series is one repetition per point. Everything else here is the median of two. So the 40.6M figure has no median behind it โ it is a single run. I've left it in because the shape (it scales linearly while the realistic client plateaus) reproduces across all five core counts, but treat the exact digits as ยฑ.
- Garnet's 21.4M is a floor, not a ceiling. At 48 cores the Garnet server still had CPU headroom and my client box ran out first. I was measuring my load generator. "At least 21.4M" is doing real work in that sentence.
- Single-node throughput, not a distributed-systems comparison. No failover, no replication lag, no multi-node Dragonfly or Garnet cluster mode. Durability is off on every engine, identically โ this is a cache comparison.
- Memory excludes Garnet on purpose. It doesn't report
used_memorythe way the RESP engines do (it pre-allocates a log and reports .NET GC internals), so a bytes/key figure would have been apples-to-oranges. Better to say nothing than something dishonest.
Hardware, both sessions: AWS c7i.metal-24xl server โ bare metal, Intel Xeon 8488C (Sapphire Rapids), 48 physical cores, single NUMA node, 192 GB. Client on its own over-provisioned box, same AZ and placement group, us-east-1. Every run proven server-bound before it counted. Keyspace pre-populated so reads hit real data (hit_rate = 1.0 on every row below). Client-side latency only โ never INFO numbers, which are not comparable across these engines.
Table A โ Session 1 (Sep 1): Redis, Valkey, Dragonfly
48 cores ยท read-heavy (SET:GET 1:10) ยท 100-byte values ยท pipeline 16 ยท medians of 2 reps (ceiling: 1 rep) ยท latency is client-side, in milliseconds.
| Configuration | Throughput | ops/core | p50 | p99 | p99.9 | bytes/key |
|---|---|---|---|---|---|---|
| Redis Cluster โ fully driven (per-shard routing) | 40.6M | 845K | 0.56 | 1.51 | 4.64 | 165.3 |
| Valkey Cluster โ fully driven | 40.2M | 837K | 0.57 | 1.32 | 3.50 | 168.7 |
| Dragonfly โ one process | 15.5M | 322K | 0.88 | 2.42 | 3.33 | 146.1 |
| Redis Cluster โ realistic (one normal client) | 4.6M | 95K | 83.97 | 138.24 | 150.53 | 165.3 |
| Valkey Cluster โ realistic | 4.5M | 94K | 85.76 | 140.80 | 157.70 | 168.7 |
Three things fall out of that table:
- Dragonfly is 3.4ร a realistic cluster for one process and no sharding, and reaches 38% of the raw ceiling for near-zero operational effort.
- The realistic cluster's tail is catastrophic โ 84ms p50 against Dragonfly's 0.88ms. That isn't the server being slow; it's requests queuing client-side because one cluster-mode client can't keep 48 shards busy. The same cluster, driven per-shard, does 0.56ms p50.
- Dragonfly is ~12โ13% leaner in memory (146 vs 165/169 bytes/key). Of everything here, this is the number least sensitive to how you run the test.
Scaling: the three shapes
Read-heavy, pipelined, Mops/s by core count. This is the chart that matters more than any single figure.
| series | 4c | 8c | 16c | 24c | 48c |
|---|---|---|---|---|---|
| Dragonfly | 2.0 | 3.7 | 6.5 | 9.0 | 15.5 |
| Redis (realistic client) | 3.2 | 5.0 | 5.0 | 4.8 | 4.6 |
| Redis (fully driven) | 5.2 | 9.2 | 15.8 | 22.5 | 40.6 |
| Valkey (realistic client) | 3.1 | 4.9 | 4.9 | 4.8 | 4.5 |
| Valkey (fully driven) | 5.0 | 8.8 | 15.2 | 21.7 | 40.2 |
Dragonfly climbs. The driven ceiling climbs faster. The realistic cluster stops improving at 8 cores and then very slightly declines โ adding shards past that point made a normal client worse, not better. Dragonfly overtakes the realistic cluster at about 16 cores.

Full story โ Part 3: Why a normal client gets 4.6M out of a cluster that can do 40M
Latency under load

Dragonfly and a well-driven cluster are both sub-millisecond at p50. A naive cluster client is ~95ร worse, and that gap is client-side queuing, not server work. โ Part 4: Latency under load
Memory efficiency

1M keys ร 100B, baseline-subtracted: Dragonfly 146.1 ยท Redis 165.3 ยท Valkey 168.7 ยท KeyDB 200.3 bytes/key. Hardware-independent and the least disputable number in the project. โ Part 5: Memory efficiency
The cross-key tax

This is Dragonfly's structural advantage and it has nothing to do with ops/s. On a Redis or Valkey cluster, plain multi-key operations across the keyspace are rejected outright:
MGET alpha bravo charlie -> CROSSSLOT Keys in request don't hash to the same slot
EVAL over 3 plain keys -> CROSSSLOT Keys in request don't hash to the same slot
MGET {u1}:a {u1}:b -> OK (hash-tagged, same slot)
Dragonfly runs all three freely as one process: MGET(10) at 2.4M ops/s, MSET(10) at 1.3M ops/s at 48 cores. On a cluster, the cost isn't latency โ it's redesigning your key names around hash tags, forever. โ Part 6: Operational simplicity, quantified
Table B โ Session 2 (Sep 9): KeyDB and Garnet
Different load generator (AMD c7a.24xlarge), so these are only comparable to each other, not to Table A. The same-day Redis reference figures and why they moved are in the KeyDB/Garnet write-up.

| Configuration | Throughput | p50 | p99 | bytes/key |
|---|---|---|---|---|
| Garnet โ one process, 48 cores | โฅ21.4M (client-limited) | 0.68 | 1.63 | not measured |
| KeyDB โ one process, 16 threads (its maximum) | 636K | 22.85 | 64.26 | 200.3 |
KeyDB found a wall, not a slope
| cores | 4 | 8 | 16 | 24 | 48 |
|---|---|---|---|---|---|
| KeyDB ops/s | 413K | 569K | 636K | won't start | won't start |
| KeyDB p50 (ms) | 28.86 | 22.78 | 22.85 | โ | โ |
Doubling from 8 to 16 cores bought 12% โ the signature of lock contention. And above 16 threads KeyDB 6.3.4 doesn't slow down, it refuses to boot:
*** FATAL CONFIG FILE ERROR (KeyDB 6.3.4) ***
'server-threads "24"'
Invalid number of threads specified
On a 48-core box, KeyDB's multithreading tops out at a third of the machine, at 22โ29ms p50 while it does it. It is the clearest answer I've found to "why did Dragonfly rewrite from scratch instead of just doing what KeyDB did?" โ the fork approach ran out of runway.
Garnet scaled further than I expected
| cores | 4 | 8 | 16 | 24 | 48 |
|---|---|---|---|---|---|
| Garnet ops/s | 4.1M | 8.1M | 15.8M | 19.0M | 21.4M+ |
| Garnet p50 (ms) | 3.39 | 1.72 | 0.78 | 0.60 | 0.68 |
Near-linear to 16 cores, still climbing at 48, sub-millisecond p50 from 16 cores on. I checked server CPU on every run before believing it โ at 24 cores it peaked at 2204% of a 2400% budget, at 48 cores ~4000% of 4800%, comfortably inside its pinned cores, hit rate 1.0 throughout. Then the client saturated, so 21.4M is where my load generator gave up, not where Garnet did.
Microsoft's .NET engine deserves far more independent benchmarking than it gets. โ Full write-up: KeyDB and Garnet
So which one should you run?

| If this is your situation | Run this | Why |
|---|---|---|
| One big box, want the cores used, don't want to operate a cluster | Dragonfly | 3.4ร a realistic cluster, one process, multi-key just works |
| Already on Redis, throughput is fine, you value the ecosystem | Stay on Redis | The engine is rarely the bottleneck โ check your client first |
| Licensing/governance matters more than the last 2% | Valkey | Measured within noise of Redis on every axis here |
| You need absolute peak and can build per-shard routing | Redis/Valkey Cluster, driven properly | 40M is real โ but you must earn it client-side |
| Memory cost per key dominates your bill | Dragonfly | 12โ13% leaner, and it's the most robust number here |
| On .NET, or willing to run something newer | Evaluate Garnet | Scaled furthest of anything I tested; verify it yourself |
| Considering KeyDB in 2026 | Don't, without testing | Hard 16-thread cap, weak scaling, heaviest memory |
The honest headline is not "X wins." It's that on modern many-core hardware the shape of the scaling curve, and how hard the engine is to drive properly, matter more than any single ops/s number. โ Part 7: When to use which
Reproduce it, and tell me where I'm wrong
That's the whole point of publishing the harness.
git clone https://github.com/sunnysahijwani/dragonfly-redis-valkey-benchmark
cd dragonfly-redis-valkey-benchmark
# single box, quick run (Docker required)
bash scripts/run-phase-a.sh
# the fully-driven cluster ceiling
bash scripts/cluster-saturate.sh redis <server-ip> 7001 <shards>
# regenerate every table above from the raw data
python3 analysis/analyze-aws.py
Pinned versions: Redis 8.2.8 ยท Valkey 8.1.9 ยท Dragonfly v1.40.1 ยท KeyDB 6.3.4 ยท Garnet 2.1.6 ยท memtier_benchmark 2.5.1 โ all images pinned by digest, every knob recorded per row.
Raw data: results/runs-aws.csv (350 runs) plus the session-2 capture โ re-derive every number on this page.
Repo: github.com/sunnysahijwani/dragonfly-redis-valkey-benchmark (MIT)

If you only read one part of the series, read the methodology โ including the bias I caught in my own setup, where a false reading was off by 350ร on the same machine. โ Part 1: How I kept it honest
The full series
- How I kept it honest โ methodology & fairness โ the traps that make most in-memory benchmarks lie, and how I disarmed each one. Start here.
- Throughput & scaling on 48 cores โ the full setup, every config and tweak, and the chart where three completely different shapes appear.
- Why a normal client gets 4.6M out of a cluster that can do 40M โ a debugging story that became the most interesting finding.
- Latency under load โ p50/p99/p99.9, and why the naive-cluster tail explodes.
- Memory efficiency โ bytes per key; the least-disputable number in the series.
- Operational simplicity: the cross-key tax โ cross-slot, hash tags, multi-key and Lua, quantified.
- When to use which โ the decision table and the three-way trade-off.
Follow-ups: KeyDB and Garnet on the same harness ยท How long a Redis Sentinel failover actually takes ยท the interactive explorer
Methodology reviewed against the DragonflyDB team's benchmarking notes before publishing. Benchmarked on AWS c7i.metal-24xl (48 physical Sapphire Rapids cores) with a dedicated client instance, us-east-1, same placement group.
About the author
I'm Sunny Sahijwani โ a senior backend & DevOps engineer.
๐ Connect with me on LinkedIn โ I'm always happy to talk in-memory databases, performance, and systems architecture.
The full harness, pinned versions, and raw data for this benchmark are public on GitHub โ rerun it and tell me where I'm wrong.

