Databases — Redis & Compatible Alternatives
Redis
Purpose: High-performance in-memory data store used for caching, session management, message brokering, and real-time analytics. Used as a dependency by Nextcloud, Immich, Authentik, and many others.
# ~/redis/compose.yaml
services:
redis:
image: redis:7-alpine
ports:
- 127.0.0.1:6379:6379
volumes:
- redis_data:/data
command: redis-server --appendonly yes
restart: unless-stopped
volumes:
redis_data:
cd ~/redis && podman-compose up -d
Common operations
# Interactive CLI
podman exec -it redis redis-cli
# Ping server
podman exec redis redis-cli ping
# Set and get a key
podman exec redis redis-cli set mykey "hello"
podman exec redis redis-cli get mykey
# Monitor all commands in real time
podman exec redis redis-cli monitor
# Show server info and stats
podman exec redis redis-cli info
# List all keys (careful on large datasets)
podman exec redis redis-cli keys "*"
# Show memory usage
podman exec redis redis-cli info memory | grep used_memory_human
# Flush all keys (destructive!)
podman exec redis redis-cli flushall
# Save snapshot now
podman exec redis redis-cli bgsave
# Show connected clients
podman exec redis redis-cli client list
Test:podman exec -it redis redis-cli pingMonitor:podman exec -it redis redis-cli monitor
Redis Data Structures
Redis is not just a key-value store — it has five core data types, each suited to different use cases:
String: — the default. Any binary-safe value up to 512 MB. Used for caching, counters, rate limiting.
SET session:abc123 '{"user_id": 42}' EX 3600 # with 1-hour TTL
INCR page_views:home # atomic counter
List: — ordered, allows duplicates. Implemented as a doubly-linked list. Used for queues and activity feeds.
LPUSH jobs:email '{"to":"alice@example.com"}' # push to head (producer)
BRPOP jobs:email 30 # blocking pop from tail (consumer, 30s timeout)
Set: — unordered, unique members. Used for tags, unique visitors, friend lists.
SADD online_users user:42 user:99
SISMEMBER online_users user:42 # is user:42 online?
SINTER premium_users active_users # intersection: premium AND active
Sorted Set: — unique members each with a float score. Members are ordered by score. Used for leaderboards, priority queues, rate limiting with sliding windows.
ZADD leaderboard 9850 "alice" 7200 "bob"
ZRANGE leaderboard 0 9 REV WITHSCORES # top 10, highest score first
ZADD leaderboard INCR 100 "alice" # add 100 to alice's score
Hash: — field-value pairs within a single key. More memory-efficient than storing each field as a separate string key. Used for objects, user profiles, configuration.
HSET user:42 name "Alice" email "alice@example.com" role "admin"
HGET user:42 email
HGETALL user:42
Pub/Sub vs Streams vs Lists for messaging
- Pub/Sub (
SUBSCRIBE,PUBLISH) — fire-and-forget. Messages are delivered to current subscribers only; no persistence, no acknowledgement. - Lists with
BRPOP— simple work queue. One producer, one consumer per message. Good for tasks. - Streams (
XADD,XREADGROUP) — persistent, consumer-group-aware event log. Replay, acknowledgement, multiple consumer groups. The closest Redis equivalent to Kafka.
Redis Persistence Modes
Redis has two persistence mechanisms with fundamentally different trade-offs:
RDB (Redis Database Snapshot): — point-in-time snapshots saved to disk periodically. Compact, fast to load on restart, but you lose all writes since the last snapshot if Redis crashes.
AOF (Append-Only File): — every write command is appended to a log file. Configurable fsync policy: always (safe, slow), everysec (default, loses at most 1 second of data), no (fastest, OS decides).
# Enable AOF (what --appendonly yes does)
redis-server --appendonly yes --appendfsync everysec
# Enable RDB snapshots every 60 seconds if 1000 keys changed
redis-server --save 60 1000
# Use both (recommended for production)
redis-server --appendonly yes --save 900 1 --save 300 10 --save 60 10000
Trade-off summary
RDB gives faster restarts and smaller files; AOF gives better durability. For a homelab cache, losing a few seconds of data on crash is usually acceptable — use AOF with everysec. For session storage or queues where losing data matters, use always or run both.
Valkey
Purpose: The Linux Foundation's open-source fork of Redis, created after the Redis licence change. Drop-in compatible with all Redis clients — just swap the image. Recommended if you want fully open-source Redis semantics under the BSD licence going forward.
# ~/valkey/compose.yaml
services:
valkey:
image: valkey/valkey:8-alpine
ports:
- 127.0.0.1:6379:6379
volumes:
- valkey_data:/data
command: valkey-server --appendonly yes
restart: unless-stopped
volumes:
valkey_data:
cd ~/valkey && podman-compose up -d
Valkey is wire-protocol compatible with Redis 7.2. Any Jedis, redis-py, or ioredis client connects without modification.
KeyDB
Purpose: Multithreaded Redis fork optimised for modern multi-core CPUs. Drop-in compatible with all Redis clients — just swap the image. KeyDB typically achieves 2–5× higher throughput than Redis on multi-core hosts.
# ~/keydb/compose.yaml
services:
keydb:
image: eqalpha/keydb:alpine
ports:
- 127.0.0.1:6379:6379
volumes:
- keydb_data:/data
restart: unless-stopped
volumes:
keydb_data:
cd ~/keydb && podman-compose up -d
Dragonfly (Modern Redis/Memcached Replacement)
Purpose: High-performance, multi-threaded in-memory data store with full Redis and Memcached API compatibility. Uses a shared-nothing architecture that scales linearly with CPU cores — benchmarks show 25× higher throughput than Redis on a 16-core machine. Also uses 30–40% less RAM than Redis for the same dataset. Drop-in replacement: no code changes, same client libraries, same commands.
# ~/dragonfly/compose.yaml
services:
dragonfly:
image: docker.dragonflydb.io/dragonflydb/dragonfly
ports:
- 127.0.0.1:6380:6379
volumes:
- /home/user/dragonfly/data:/data:Z
ulimits:
memlock: -1
restart: unless-stopped
cd ~/dragonfly && podman-compose up -d
Common operations
# Connect with redis-cli (Dragonfly is fully compatible)
podman exec -it dragonfly redis-cli -p 6379
# Ping
podman exec dragonfly redis-cli -p 6379 ping
# Check info and memory usage
podman exec dragonfly redis-cli -p 6379 info memory | grep used_memory_human
# Monitor commands in real time
podman exec dragonfly redis-cli -p 6379 monitor
# Save snapshot
podman exec dragonfly redis-cli -p 6379 bgsave
Use port6380on the host to avoid conflicts with an existing Redis instance. Any Redis client connects tolocalhost:6380without modification.