Skip to content
Unverified — AI-generated content. Help verify this page

Redis vs Memcached vs KeyDB vs DragonflyDB

In-memory data stores are the performance escape hatch that every production system eventually needs. Redis became the de facto standard, but its single-threaded architecture and recent licensing changes have opened the door for competitors. This comparison evaluates four options across the dimensions that actually matter: data structures, persistence, scaling, and performance under realistic workloads.

Overview

StoreFirst ReleaseLanguageThreading ModelLicense
Redis2009CSingle-threaded (I/O threads for network)SSPL (was BSD, changed 2024)
Memcached2003CMulti-threadedBSD
KeyDB2019C++ (Redis fork)Multi-threadedBSD-3
DragonflyDB2022C++Multi-threaded (shared-nothing)BSL 1.1

Redis License Change

Redis switched from BSD to the Server Side Public License (SSPL) in March 2024. This means cloud providers cannot offer Redis-as-a-service without a commercial agreement. If open-source licensing matters, consider Valkey (Linux Foundation fork of Redis 7.2.4, BSD licensed), KeyDB, or DragonflyDB.

Architecture Comparison

Feature Matrix

FeatureRedisMemcachedKeyDBDragonflyDB
Data structuresStrings, Lists, Sets, Sorted Sets, Hashes, Streams, HyperLogLog, Bitmaps, GeospatialStrings onlySame as RedisSame as Redis (compatible)
PersistenceRDB snapshots + AOFNoneRDB + AOF (fork-free snapshots)RDB snapshots (fork-free)
ReplicationMaster-replicaNoneMulti-master (Active Replica)Master-replica
ClusteringRedis Cluster (hash slots)Client-side shardingRedis Cluster compatibleSingle-instance (scales vertically)
Pub/SubYesNoYesYes
Lua scriptingYes (Lua 5.1)NoYesYes
TransactionsMULTI/EXECNo (CAS only)MULTI/EXECMULTI/EXEC
TTL granularityMillisecondSecondMillisecondMillisecond
Eviction policies8 policies (LRU, LFU, etc.)LRU only8 policies (same as Redis)8 policies (same as Redis)
TLSYesYes (since 1.5.13)YesYes
ACLYes (Redis 6+)SASL auth onlyYesYes
ModulesRedisJSON, RediSearch, RedisGraph, etc.NoneRedis modules (partial)Built-in JSON, Search
Sentinel (HA)Redis SentinelNot applicableNot needed (multi-master)Not yet
Memory efficiencyjemalloc, 1x baselineSlab allocator, ~0.9xjemalloc, ~1xDashtable, ~0.3-0.5x
Max memoryLimited by single-thread throughputLimited by OSLimited by CPU coresUp to 1 TB per instance
ProtocolRESP2 / RESP3Memcached text/binaryRESP2 / RESP3RESP2 / RESP3

Code & Config Comparison

Client Usage

All four support the Redis protocol (except Memcached), so client code is often identical for Redis, KeyDB, and DragonflyDB.

Redis / KeyDB / DragonflyDB (identical client code):

typescript
import Redis from 'ioredis';

// Connection — same for Redis, KeyDB, and Dragonfly
const redis = new Redis({
  host: '127.0.0.1',
  port: 6379,
  password: 'secret',
  db: 0,
  retryStrategy: (times) => Math.min(times * 50, 2000),
});

// Strings
await redis.set('user:1:name', 'Alice', 'EX', 3600);
const name = await redis.get('user:1:name');

// Hashes
await redis.hset('user:1', { name: 'Alice', email: 'alice@example.com', age: '30' });
const user = await redis.hgetall('user:1');

// Sorted Sets (leaderboard)
await redis.zadd('leaderboard', 100, 'alice', 95, 'bob', 87, 'charlie');
const topPlayers = await redis.zrevrange('leaderboard', 0, 9, 'WITHSCORES');

// Lists (job queue)
await redis.lpush('jobs:pending', JSON.stringify({ type: 'email', to: 'alice@example.com' }));
const job = await redis.brpop('jobs:pending', 30); // blocking pop with timeout

// Streams (event log)
await redis.xadd('events', '*', 'type', 'page_view', 'url', '/home', 'user', 'alice');
const events = await redis.xrange('events', '-', '+', 'COUNT', 100);

// Pub/Sub
const sub = redis.duplicate();
await sub.subscribe('notifications');
sub.on('message', (channel, message) => {
  console.log(`Received on ${channel}: ${message}`);
});
await redis.publish('notifications', 'New order received');

// Pipeline (batch commands)
const pipeline = redis.pipeline();
pipeline.incr('page_views');
pipeline.incr('api_calls');
pipeline.expire('page_views', 86400);
await pipeline.exec();

Memcached:

typescript
import Memcached from 'memcached';

const memcached = new Memcached('127.0.0.1:11211');

// Only strings — no data structures
memcached.set('user:1:name', 'Alice', 3600, (err) => {
  if (err) console.error(err);
});

memcached.get('user:1:name', (err, data) => {
  console.log(data); // 'Alice'
});

// CAS (Compare-And-Swap) for atomic updates
memcached.gets('counter', (err, data) => {
  const cas = data.cas;
  memcached.cas('counter', parseInt(data['counter']) + 1, cas, 3600, (err) => {
    // Succeeds only if no one else modified the value
  });
});

// No pub/sub, no lists, no sorted sets, no streams
// For complex data: JSON.stringify/parse everything
memcached.set('user:1', JSON.stringify({
  name: 'Alice',
  email: 'alice@example.com',
}), 3600, (err) => {});

Server Configuration

Redis (redis.conf):

conf
# Memory
maxmemory 4gb
maxmemory-policy allkeys-lfu

# Persistence
save 900 1
save 300 10
save 60 10000
appendonly yes
appendfsync everysec

# Networking
bind 0.0.0.0
protected-mode yes
requirepass your-secret-password
tcp-backlog 511

# Threading (Redis 6+)
io-threads 4
io-threads-do-reads yes

# Replication
replicaof 10.0.0.1 6379

KeyDB (keydb.conf):

conf
# Same as redis.conf, plus:

# Multi-threading (the key differentiator)
server-threads 4
server-thread-affinity true

# Active replication (multi-master)
active-replica yes
replicaof 10.0.0.2 6379

# Flash storage tier (extend memory to SSD)
storage-provider flash /var/lib/keydb/flash
maxmemory 4gb
# Data beyond 4GB spills to SSD automatically

DragonflyDB (flags):

bash
# DragonflyDB uses command-line flags
dragonfly \
  --port 6379 \
  --maxmemory 4gb \
  --dbfilename dump.rdb \
  --dir /var/lib/dragonfly \
  --requirepass your-secret-password \
  --cache_mode true \
  --keys_output_limit 8192 \
  --hz 100 \
  --snapshot_cron "*/30 * * * *"
  # Threads are auto-detected (1 per CPU core)

Docker Compose Comparison

yaml
version: '3.8'
services:
  # Redis with persistence
  redis:
    image: redis:7-alpine
    command: redis-server --requirepass secret --maxmemory 2gb --maxmemory-policy allkeys-lfu --appendonly yes
    ports:
      - "6379:6379"
    volumes:
      - redis-data:/data

  # KeyDB with multi-threading
  keydb:
    image: eqalpha/keydb:latest
    command: keydb-server --requirepass secret --server-threads 4 --maxmemory 2gb
    ports:
      - "6380:6379"
    volumes:
      - keydb-data:/data

  # DragonflyDB (auto-threads)
  dragonfly:
    image: docker.dragonflydb.io/dragonflydb/dragonfly
    command: dragonfly --requirepass secret --maxmemory 2gb --cache_mode
    ports:
      - "6381:6379"
    volumes:
      - dragonfly-data:/data

  # Memcached
  memcached:
    image: memcached:1.6-alpine
    command: memcached -m 2048 -t 4
    ports:
      - "11211:11211"

volumes:
  redis-data:
  keydb-data:
  dragonfly-data:

Performance

Throughput Benchmarks (Single Instance)

OperationRedis (1 thread)Memcached (4 threads)KeyDB (4 threads)DragonflyDB (auto)
SET (pipeline)~500K ops/s~1M ops/s~1.5M ops/s~4M ops/s
GET (pipeline)~600K ops/s~1.2M ops/s~2M ops/s~4M ops/s
SET (no pipeline)~100K ops/s~200K ops/s~300K ops/s~800K ops/s
GET (no pipeline)~120K ops/s~250K ops/s~350K ops/s~900K ops/s
ZADD~80K ops/sN/A~200K ops/s~600K ops/s
LPUSH/LPOP~100K ops/sN/A~250K ops/s~700K ops/s
HSET~90K ops/sN/A~220K ops/s~650K ops/s

Benchmark Context

These numbers are from memtier_benchmark with default settings on an 8-core machine. Real-world performance depends on key sizes, value sizes, network latency, and access patterns. DragonflyDB's numbers are impressive but come from a shared-nothing architecture that trades some consistency guarantees for throughput.

Memory Efficiency

MetricRedisMemcachedKeyDBDragonflyDB
Overhead per key~60 bytes~48 bytes + slab overhead~60 bytes~20-30 bytes
1M keys (64B values)~130 MB~120 MB~130 MB~50-70 MB
10M keys (64B values)~1.3 GB~1.2 GB~1.3 GB~500-700 MB
Memory allocatorjemallocSlab allocatorjemallocCustom (Dashtable)
Memory fragmentationModerateLow (slabs)ModerateLow (compact)
Snapshot memory2x (fork + COW)N/A1x (fork-free)1x (fork-free)

Redis Fork Overhead

Redis creates RDB snapshots by forking the process, which can temporarily double memory usage due to copy-on-write page duplication under write-heavy workloads. DragonflyDB and KeyDB use fork-free snapshot algorithms that avoid this problem. For large datasets (>32 GB), this is a significant operational advantage.

Latency Profiles

PercentileRedisMemcachedKeyDBDragonflyDB
p500.1ms0.1ms0.1ms0.1ms
p990.5ms0.3ms0.4ms0.3ms
p99.92ms0.8ms1ms0.8ms
p99.9 during snapshot50-200msN/A1ms0.8ms

Developer Experience

Strengths

Redis:

  • The richest data structure library (Sorted Sets, Streams, HyperLogLog, etc.)
  • Massive ecosystem: every language has a mature client library
  • Redis Modules (RediSearch, RedisJSON, RedisTimeSeries) extend functionality
  • Redis Cluster for horizontal scaling beyond single-node limits
  • 15+ years of production battle-testing

Memcached:

  • Simplest possible API: get, set, delete, incr, decr
  • True multi-threaded from day one — no single-thread bottleneck
  • Predictable memory usage via slab allocator
  • Nearly impossible to misconfigure
  • Perfect for simple key-value caching with no persistence needed

KeyDB:

  • Drop-in Redis replacement (wire-compatible, same config)
  • Multi-threaded command processing (not just I/O threads)
  • Active Replica: multi-master replication for read scaling
  • FLASH storage tier: extend cache beyond RAM to SSD
  • BSD licensed (no SSPL concerns)

DragonflyDB:

  • 10-25x throughput vs Redis on the same hardware
  • 50-70% less memory per key (Dashtable data structure)
  • Fork-free snapshots: no memory spikes during persistence
  • Single instance can replace a Redis Cluster for most workloads
  • Redis-compatible protocol (works with existing Redis clients)

Pain Points

StoreKey Limitation
RedisSingle-threaded bottleneck on CPU-bound workloads; SSPL license; snapshot memory doubling
MemcachedNo data structures beyond strings; no persistence; no pub/sub; no scripting
KeyDBSmaller community; lags behind Redis feature releases; some module incompatibilities
DragonflyDBBSL license; no clustering yet; younger project (less battle-tested); some Redis command gaps

When to Use Which

Decision Summary

ScenarioRecommended Store
Simple caching, no persistenceMemcached
General-purpose cache + data structuresRedis
Need open-source Redis alternativeValkey or KeyDB
High throughput, single nodeDragonflyDB
Multi-master replicationKeyDB (Active Replica)
Session storageRedis or KeyDB
Job/message queueRedis (Streams/Lists) or DragonflyDB
Leaderboards / rankingRedis (Sorted Sets)
Rate limitingRedis or DragonflyDB
Feature flags / config storeRedis + persistence
Very large dataset (>100 GB)KeyDB (FLASH tier) or DragonflyDB
Horizontal scaling to many nodesRedis Cluster or Valkey Cluster

Migration

Redis to DragonflyDB

bash
# DragonflyDB is wire-compatible with Redis
# Migration is straightforward:

# 1. Start DragonflyDB
docker run -d --name dragonfly \
  -p 6380:6379 \
  docker.dragonflydb.io/dragonflydb/dragonfly \
  --requirepass secret

# 2. Migrate data using redis-cli
# Option A: RDB file
redis-cli -h redis-host -a secret --rdb /tmp/dump.rdb
# Copy dump.rdb to DragonflyDB data directory and restart

# Option B: Live migration with REPLICAOF
# DragonflyDB can act as a replica of Redis
dragonfly --replicaof redis-host:6379

# 3. Update application connection string
# Change host from redis-host to dragonfly-host
# No code changes needed — same Redis protocol

# 4. Verify compatibility
redis-cli -h dragonfly-host -p 6379 -a secret
> SET test "hello"
> GET test
> ZADD myset 1 "a" 2 "b"
> ZRANGE myset 0 -1 WITHSCORES

# 5. Monitor for unsupported commands
# DragonflyDB logs warnings for unsupported commands
# Check: MODULE commands, some CLUSTER commands, DEBUG commands

Memcached to Redis

bash
# Memcached to Redis requires code changes
# because the protocols are different

# 1. Install Redis
docker run -d --name redis -p 6379:6379 redis:7

# 2. Update client library
# Before: memcached client
npm uninstall memcached
npm install ioredis

# 3. Update connection code
# Before:
#   const memcached = new Memcached('127.0.0.1:11211');
#   memcached.set('key', 'value', 3600, callback);
#
# After:
#   const redis = new Redis({ host: '127.0.0.1', port: 6379 });
#   await redis.set('key', 'value', 'EX', 3600);

# 4. Warm the cache
# Option A: Let the cache warm naturally (accept cache misses)
# Option B: Pre-populate from your database
# There's no automatic Memcached → Redis migration tool

Redis to Valkey (Post-License-Change)

bash
# Valkey is a drop-in fork of Redis 7.2.4 (BSD licensed)

# 1. Install Valkey
docker run -d --name valkey -p 6379:6379 valkey/valkey:7.2

# 2. Copy RDB file from Redis
redis-cli -h redis-host BGSAVE
cp /var/lib/redis/dump.rdb /var/lib/valkey/dump.rdb

# 3. Start Valkey with the RDB file
# Valkey reads Redis RDB format natively

# 4. Update client connection
# No code changes — same RESP protocol
# Just change the hostname

# 5. Verify
valkey-cli ping  # PONG
valkey-cli info server  # Shows Valkey version

Migration Complexity

Redis to DragonflyDB/KeyDB/Valkey: trivial (same protocol, same RDB format, same client libraries). Memcached to Redis: moderate (different protocol, different client library, but simple API surface). Always run both systems in parallel during migration and compare response correctness.

Verdict

Redis remains the king of in-memory data stores. Its data structure library, module ecosystem, cluster support, and 15 years of battle-testing make it the safe default. The SSPL license change is the only significant concern — if it matters to you, Valkey is the community-maintained BSD fork.

Memcached is the right choice when you need the simplest possible cache. If your workload is purely key-value with no data structures, no persistence, and no pub/sub, Memcached's multi-threaded simplicity is an advantage, not a limitation.

KeyDB is the best Redis alternative for teams that need multi-threading, active replication, or SSD-backed caching while staying on a BSD license. Its wire compatibility with Redis makes migration trivial.

DragonflyDB is the performance breakthrough. On a single instance, it delivers 10-25x the throughput of Redis with 50-70% less memory. If your workload can be served by a single node (most can), DragonflyDB eliminates the need for Redis Cluster entirely.

Bottom Line

Start with Redis (or Valkey if license matters) for most use cases — the ecosystem is unmatched. Reach for DragonflyDB when you need maximum throughput per dollar. Use Memcached when you want dead-simple key-value caching. Consider KeyDB when you need multi-master replication or SSD-tiered storage with Redis compatibility.

Which Would You Choose?

Scenario 1: You need a cache for a high-traffic web app. Cache entries are simple key-value strings with TTLs. No pub/sub, no sorted sets, no persistence needed.

Recommendation: Memcached

Memcached is purpose-built for this exact use case. Multi-threaded from day one, dead-simple API, predictable memory usage via the slab allocator. Adding Redis's data structure overhead is unnecessary when all you need is get/set/delete.

Scenario 2: You are running a 6-node Redis Cluster for a gaming leaderboard. Each node handles 100K ops/s, and your infrastructure team is tired of managing cluster topology. You want to consolidate to fewer, more powerful nodes.

Recommendation: DragonflyDB

A single DragonflyDB instance can handle 4M+ ops/s — replacing your entire 6-node Redis Cluster with one or two DragonflyDB instances. Sorted Sets work identically (same RESP protocol, same client libraries). Fork-free snapshots eliminate the memory doubling during persistence.

Scenario 3: Your company's legal team says you cannot use SSPL-licensed software. You need a Redis-compatible in-memory store with persistence, pub/sub, and sorted sets.

Recommendation: Valkey or KeyDB

Valkey is the Linux Foundation's BSD-licensed fork of Redis 7.2.4 — it is a drop-in replacement with the same protocol, same RDB format, and same client libraries. KeyDB offers the additional advantage of multi-threading and active-replica multi-master replication, also under a BSD license.

Common Misconceptions

  • "Redis is single-threaded and therefore slow" — Redis handles 100K+ ops/s on a single thread because most operations are memory-bound, not CPU-bound. I/O threads (Redis 6+) handle network read/write in parallel. Single-threaded command processing actually simplifies concurrency and eliminates lock contention.
  • "DragonflyDB is just a faster Redis" — DragonflyDB uses a fundamentally different architecture (shared-nothing, per-core sharding) that trades some consistency guarantees for throughput. It is not a drop-in replacement for all Redis use cases — verify that your specific commands and patterns are supported.
  • "Memcached is obsolete" — Memcached is still the right tool for pure key-value caching. Facebook (Meta) runs one of the world's largest Memcached deployments. It is not obsolete; it is specialized.
  • "Redis license change means Redis is no longer usable" — The SSPL license only restricts competitive cloud hosting services. End-user deployment is unaffected. If licensing concerns you, Valkey is a community fork under the original BSD license.

Real Migration Stories

Twitter/X: Memcached to Redis — Twitter migrated from Memcached to Redis for their timeline caching because they needed sorted sets for time-ordered feeds and pub/sub for real-time notifications. The migration demonstrated that when your use case grows beyond simple key-value caching, Redis's data structures justify the switch.

Snap (Snapchat): Redis to KeyDB — Snap adopted KeyDB for workloads that exceeded single-threaded Redis throughput limits. KeyDB's multi-threaded architecture delivered the throughput they needed without the operational complexity of Redis Cluster, while maintaining full Redis protocol compatibility.

Quiz

1. Why does Redis fork the process for RDB snapshots, and what is the problem with this approach?

Redis uses fork() to create a child process that writes the snapshot while the parent continues serving requests. Copy-on-write means modified pages are duplicated, which can temporarily double memory usage under write-heavy workloads. DragonflyDB and KeyDB solve this with fork-free snapshot algorithms.

2. What is DragonflyDB's "shared-nothing" architecture?

Each CPU core runs an independent fiber with its own memory shard. There are no locks or shared data structures between cores. Requests are routed to the core that owns the relevant key shard. This eliminates lock contention and scales linearly with core count.

3. Why might you choose Memcached over Redis for a simple caching layer?

Memcached is multi-threaded by design (no single-thread bottleneck), uses a slab allocator for predictable memory (no fragmentation), and has a simpler API surface (fewer ways to misconfigure). For pure key-value caching with no data structure needs, Memcached's simplicity is an advantage.

4. What is Valkey, and how does it relate to Redis?

Valkey is a Linux Foundation fork of Redis 7.2.4, created in March 2024 after Redis changed from BSD to SSPL license. It is a drop-in replacement that maintains the BSD license, same protocol (RESP), same RDB format, and same client library compatibility.

5. What is KeyDB's "Active Replica" feature?

Active Replica enables multi-master replication where multiple KeyDB nodes accept writes simultaneously. Writes are propagated asynchronously between masters. This enables horizontal write scaling without the complexity of Redis Cluster's hash slot sharding.

One-Liner Summary

Redis is the king of in-memory data structures with the largest ecosystem, DragonflyDB delivers 10-25x throughput on a single node, Memcached is the simplest pure cache, and KeyDB/Valkey offer BSD-licensed Redis alternatives.

"What I cannot create, I do not understand." — Richard Feynman