Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Design Redis architectures with caching patterns, data structures, eviction policies, persistence (RDB/AOF), and high availability (Sentinel/Cluster).
.claude/skills/williamzujkowski-redis-database-architect/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-03 | ✗→✓ | ▲ Improved | 267% | 0% |
| case-04 | ✗→✓ | ▲ Improved | 275% | 0% |
| case-11 | ✗→✓ | ▲ Improved | 748% | 0% |
| case-22 | ✗→✓ | ▲ Improved | 188% | 0% |
| case-01 | ✓→✗ | ▼ Worse | 174% | 0% |
Invoke this skill when designing, reviewing, or optimizing Redis database architectures for applications requiring sub-millisecond latency, high-throughput caching, session management, real-time analytics, or distributed data structures.
Trigger Conditions:
Out of Scope:
NOW_ET using NIST/time.gov semantics (America/New_York, ISO-8601).Abort Conditions:
Use Case: Fast path for common scenarios (80% of requests).
Steps:
| Use Case | Recommended Structure | Key Commands | Memory Efficiency | |----------|----------------------|--------------|-------------------| | Simple key-value cache | String | GET, SET, SETEX, TTL | Baseline | | Structured objects (user profiles) | Hash | HGET, HSET, HGETALL | 50-70% savings vs strings | | Recent items (activity feed) | List | LPUSH, LRANGE, LTRIM | Efficient for ordered data | | Unique items (tags, followers) | Set | SADD, SMEMBERS, SINTER | Deduplication | | Ranked items (leaderboards) | Sorted Set | ZADD, ZRANGE, ZRANK | Score-based sorting | | Event streams (logs, messages) | Stream | XADD, XREAD, XGROUP | Append-only, consumer groups | | Probabilistic (unique counts) | HyperLogLog | PFADD, PFCOUNT | 0.81% error, 12 KB max | | Membership testing (spam filter) | Bloom Filter | BF.ADD, BF.EXISTS | Space-efficient (Redis 8.0) |
Output: Use case mapping, data structure selection, top 3 quick wins.
Use Case: Comprehensive architecture for production deployments.
Steps:
Caching Patterns:
| Pattern | Description | Pros | Cons | Best For | |---------|-------------|------|------|----------| | Cache-Aside (Lazy Loading) | App checks cache first, loads from DB on miss, populates cache | Flexible, cache only what's needed | First query slow (cache miss), stale data risk | Read-heavy apps, infrequent updates | | Write-Through | App writes to cache, cache synchronously writes to DB | Strong consistency, simple invalidation | Slower writes (sync), cache all writes | Write-heavy, consistency critical | | Write-Behind (Write-Back) | App writes to cache, cache asynchronously writes to DB | Fast writes (async), batch DB writes | Potential data loss on failure, eventual consistency | High write throughput, accept eventual consistency |
Cache-Aside Example (Most Common):
pythondef get_user(user_id): # 1. Check cache user = redis.get(f"user:{user_id}") if user: return json.loads(user) # Cache hit # 2. Cache miss: load from database user = db.query("SELECT * FROM users WHERE id = ?", user_id) # 3. Populate cache with TTL redis.setex(f"user:{user_id}", 3600, json.dumps(user)) # 1 hour TTL return user
Write-Through Example:
pythondef update_user(user_id, data): # 1. Write to cache redis.hset(f"user:{user_id}", mapping=data) # 2. Synchronously write to database db.execute("UPDATE users SET ... WHERE id = ?", user_id) # Cache and DB consistent
Cache Consistency Models:
Memory Efficiency Techniques:
redis# Instead of multiple string keys (inefficient): SET user:1000:name "Alice" SET user:1000:email "alice@example.com" SET user:1000:age "30" # Use a single hash (efficient): HSET user:1000 name "Alice" email "alice@example.com" age 30 HGETALL user:1000
redis# Add players with scores ZADD leaderboard 9500 "player1" 8200 "player2" 7800 "player3" # Get top 10 players ZRANGE leaderboard 0 9 WITHSCORES REV # Get player rank ZRANK leaderboard "player1"
redis# Add event to stream XADD events * type "login" user_id 1000 timestamp 1730000000 # Read events (consumer group) XREADGROUP GROUP mygroup consumer1 COUNT 10 STREAMS events >
redis# Count unique visitors PFADD visitors:2025-10-26 "user1" "user2" "user1" # Deduplication PFCOUNT visitors:2025-10-26 # Returns ~2 (unique count)
redis# Create bloom filter with 10000 capacity, 1% error rate BF.RESERVE spam_filter 0.01 10000 # Add emails BF.ADD spam_filter "spam@example.com" # Check membership (false positive possible, no false negative) BF.EXISTS spam_filter "spam@example.com" # Returns 1 BF.EXISTS spam_filter "real@example.com" # Returns 0
8 Eviction Policies (Redis 8.0):
| Policy | Target Keys | Algorithm | Best For | |--------|-------------|-----------|----------| | noeviction | N/A (errors on OOM) | N/A | Persistent data, cannot afford data loss | | allkeys-lru | All keys | Least Recently Used | General cache, all keys eligible | | volatile-lru | Keys with TTL | Least Recently Used | Mixed workload (cache + persistent) | | allkeys-lfu | All keys | Least Frequently Used | Hotspot-heavy workloads (Redis 8.0: 16x faster) | | volatile-lfu | Keys with TTL | Least Frequently Used | Mixed workload with frequency preference | | allkeys-random | All keys | Random | Uniform access patterns | | volatile-random | Keys with TTL | Random | Simple TTL-based expiry | | volatile-ttl | Keys with TTL | Shortest TTL first | Expire soonest keys first |
Configuration Example:
redis# Set maximum memory to 4 GB (70-80% of 6 GB system RAM) CONFIG SET maxmemory 4gb # Set eviction policy to allkeys-lru CONFIG SET maxmemory-policy allkeys-lru # Verify CONFIG GET maxmemory CONFIG GET maxmemory-policy
Redis 8.0 Eviction Improvements:
3 Persistence Options:
| Option | Mechanism | Durability | Performance | Use Case | |--------|-----------|------------|-------------|----------| | RDB (Snapshots) | Point-in-time snapshots at intervals | Lose data since last snapshot | Fast (async), compact files | Backups, can tolerate data loss | | AOF (Append-Only File) | Log every write operation | Lose ≤1 sec of data (fsync everysec) | Slower writes, larger files | Durability critical | | Hybrid (RDB + AOF) | RDB snapshots + AOF log | Best of both | Balanced | Production (Redis 7.8.2+) |
RDB Configuration:
redis# Save snapshot every 900s if ≥1 key changed # Save snapshot every 300s if ≥10 keys changed # Save snapshot every 60s if ≥10000 keys changed save 900 1 save 300 10 save 60 10000
AOF Configuration (Recommended):
redis# Enable AOF appendonly yes # fsync policy (choose one): # - always: fsync every write (slowest, most durable) # - everysec: fsync every second (30% lower latency, lose ≤1s data) # - no: let OS decide (fastest, lose more data on crash) appendfsync everysec # AOF rewrite (compact log when 100% larger than last rewrite) auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb
Hybrid Persistence (Redis 7.8.2+, recommended for Redis 8.0):
redis# Enable both RDB and AOF save 900 1 appendonly yes appendfsync everysec # Redis performs RDB snapshots + AOF log for best durability
Redis Sentinel (Failover & Monitoring):
Use Case: High availability for single master, automatic failover, service discovery.
Architecture:
Configuration:
redis# sentinel.conf sentinel monitor mymaster 192.168.1.100 6379 2 # 2 = quorum (majority of 3 sentinels) sentinel down-after-milliseconds mymaster 5000 # Declare master down after 5s sentinel parallel-syncs mymaster 1 # Sync 1 replica at a time during failover sentinel failover-timeout mymaster 10000 # Failover timeout 10s
Pros:
Cons:
Redis Cluster (Sharding & Scaling):
Use Case: Horizontal scaling, data partitioning across nodes, built-in HA.
Architecture:
Configuration:
bash# Create cluster with 3 masters + 3 replicas redis-cli --cluster create \ 192.168.1.101:6379 192.168.1.102:6379 192.168.1.103:6379 \ 192.168.1.104:6379 192.168.1.105:6379 192.168.1.106:6379 \ --cluster-replicas 1
Hash Slot Distribution:
CRC16(key) mod 16384 determines slot.Pros:
Cons:
Sentinel vs Cluster Decision Matrix:
| Requirement | Redis Sentinel | Redis Cluster | |-------------|----------------|---------------| | Data size fits on single node | ✅ Yes | Not needed | | Need horizontal scaling | ❌ No | ✅ Yes | | Simple failover only | ✅ Yes | Overkill | | High availability + sharding | ❌ No | ✅ Yes | | Minimum nodes | 3 | 6 |
Redis 8.0 Performance Improvements:
Configuration Parameters:
redis# I/O Threading (Redis 8.0 - up to 112% improvement on multi-core) io-threads 4 # Set to number of CPU cores (max 8) io-threads-do-reads yes # Enable threaded reads (Redis 8.0+) # Max clients (default 10000) maxclients 50000 # Timeout for idle clients (default 0 = never) timeout 300 # Close idle clients after 5 minutes # TCP backlog (default 511, increase for high concurrency) tcp-backlog 65535 # Disable slow commands in production (optional) rename-command FLUSHDB "" rename-command FLUSHALL "" rename-command CONFIG "" # Lazy freeing (async deletion of large keys) lazyfree-lazy-eviction yes lazyfree-lazy-expire yes lazyfree-lazy-server-del yes
Memory Configuration:
redis# Set maxmemory to 70-80% of system RAM (allows OS cache) maxmemory 6gb # For 8 GB RAM server # Eviction policy maxmemory-policy allkeys-lru # Memory sampling for eviction (default 5, higher = better accuracy, slower) maxmemory-samples 10
Output: Complete architecture with caching strategy, data structures, eviction policy, persistence, HA topology, performance tuning.
Use Case: Advanced patterns, multi-region, specific use cases, version migrations.
Steps:
Rate Limiting (Fixed Window):
pythondef is_rate_limited(user_id, limit=100, window=60): key = f"rate_limit:{user_id}" current = redis.incr(key) if current == 1: redis.expire(key, window) # Set TTL on first request return current > limit # True if over limit
Rate Limiting (Sliding Window with Sorted Set):
pythondef is_rate_limited_sliding(user_id, limit=100, window=60): now = time.time() key = f"rate_limit:{user_id}" # Remove old entries outside window redis.zremrangebyscore(key, 0, now - window) # Count requests in window count = redis.zcard(key) if count < limit: redis.zadd(key, {str(uuid.uuid4()): now}) # Add new request redis.expire(key, window) return False # Not limited return True # Limited
Session Storage:
pythondef create_session(user_id, session_data, ttl=3600): session_id = str(uuid.uuid4()) key = f"session:{session_id}" # Store session as hash redis.hset(key, mapping={ "user_id": user_id, **session_data }) redis.expire(key, ttl) # Auto-expire after 1 hour return session_id
Real-Time Leaderboard:
pythondef update_leaderboard(player_id, score): redis.zadd("leaderboard", {player_id: score}) def get_leaderboard(top_n=10): # Get top N players with scores return redis.zrange("leaderboard", 0, top_n - 1, withscores=True, desc=True) def get_player_rank(player_id): rank = redis.zrevrank("leaderboard", player_id) # 0-indexed return rank + 1 if rank is not None else None
Pub/Sub (Real-Time Notifications):
python# Publisher def publish_notification(channel, message): redis.publish(channel, json.dumps(message)) # Subscriber def subscribe_notifications(channel): pubsub = redis.pubsub() pubsub.subscribe(channel) for message in pubsub.listen(): if message['type'] == 'message': data = json.loads(message['data']) handle_notification(data)
Task Queue (Simple FIFO):
python# Producer def enqueue_task(queue_name, task_data): redis.lpush(queue_name, json.dumps(task_data)) # Consumer (blocking pop) def process_tasks(queue_name): while True: # BRPOP blocks until item available (timeout 0 = infinite) _, task_json = redis.brpop(queue_name, timeout=0) task = json.loads(task_json) process_task(task)
Active-Active Geo-Replication:
Architecture:
Use Case: Global applications with local write requirements.
Benefits of Redis 8.0:
Migration Strategy (Zero-Downtime):
Risks:
Key Metrics:
redis# Server stats INFO stats # - total_commands_processed: Total commands executed # - instantaneous_ops_per_sec: Current ops/sec # - total_net_input_bytes, total_net_output_bytes: Network I/O # - evicted_keys: Keys evicted due to maxmemory # - expired_keys: Keys expired by TTL # Memory stats INFO memory # - used_memory_human: Total memory used # - used_memory_rss_human: OS-reported RSS # - mem_fragmentation_ratio: RSS / used_memory (>1.5 = fragmentation issue) # - maxmemory_human: Configured maxmemory limit # Replication stats INFO replication # - role: master or slave # - connected_slaves: Number of replicas # - master_repl_offset: Replication offset (lag indicator) # Slow log (queries >threshold) SLOWLOG GET 10 # Last 10 slow queries CONFIG SET slowlog-log-slower-than 10000 # Log queries >10ms
Prometheus Exporter:
redis_exporter for Prometheus integration.redis_uptime_in_seconds, redis_connected_clients, redis_used_memory_bytes, redis_evicted_keys_total.Output: Advanced use case patterns, multi-region architecture, migration plan, monitoring dashboards.
CONFIG SET activedefrag yes.Uncertainty Thresholds:
INFO output and slow log analysis.Required Fields:
yamlcaching_strategy: - pattern: "cache-aside" | "write-through" | "write-behind" consistency_model: "strong" | "eventual" | "ttl-based" cache_invalidation: string (how to invalidate stale data) data_structures: - use_case: string structure: "string" | "hash" | "list" | "set" | "sorted_set" | "stream" | "hyperloglog" | "bloom_filter" key_pattern: string (e.g., "user:{user_id}") commands: array (Redis commands used) memory_efficiency: string (e.g., "50% savings vs strings") eviction_policy: - maxmemory: string (e.g., "4gb") policy: "allkeys-lru" | "volatile-lru" | "allkeys-lfu" | "noeviction" | ... justification: string persistence: - type: "rdb" | "aof" | "hybrid" rdb_config: object (save intervals) if applicable aof_config: object (fsync policy) if applicable data_loss_tolerance: string (e.g., "≤1 second") high_availability: - architecture: "standalone" | "sentinel" | "cluster" topology: string (e.g., "1 master + 2 replicas + 3 sentinels") failover_time: string (e.g., "10-30 seconds") scaling_plan: string (if cluster) performance_tuning: - io_threads: integer (Redis 8.0) maxclients: integer timeout: integer (seconds) lazy_freeing: boolean estimated_improvement: string (e.g., "87% faster latency") memory_optimization: - techniques: array (hash optimization, data structure selection, etc.) estimated_savings: string (e.g., "60% memory reduction") migration_plan: # If upgrading versions - current_version: string target_version: string strategy: "replica promotion" | "blue-green" | "rolling upgrade" steps: array (migration steps) risks: array (potential issues)
Token Tier Minimums:
Cache-Aside Pattern with Hash:
python# User profile caching (60% memory savings vs JSON string) def get_user_profile(user_id): key = f"user:{user_id}" # Check cache (hash structure) if redis.exists(key): return redis.hgetall(key) # Cache hit # Cache miss: load from database user = db.query("SELECT * FROM users WHERE id = ?", user_id) # Populate cache with TTL redis.hset(key, mapping=user) redis.expire(key, 3600) # 1 hour return user
See examples/session-storage-redis-architecture.txt for a complete session management architecture.
Official Redis Documentation:
Performance & Best Practices:
Tools:
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | pass→fail | 18,273 | 13,248 | -27% | 1 | 1 | 0% | 3,941 | 10,818 | +174% | 0 | 0 | — |
case-02 | fail→fail | 5,998 | 8,815 | +47% | 1 | 1 | 0% | 1,409 | 9,829 | +598% | 0 | 0 | — |
case-03 | fail→pass | 13,926 | 12,780 | -8% | 1 | 1 | 0% | 2,848 | 10,461 | +267% | 0 | 0 | — |
case-04 | fail→pass | 14,716 | 16,200 | +10% | 1 | 1 | 0% | 2,932 | 11,006 | +275% | 0 | 0 | — |
case-05 | pass→pass | 7,003 | 7,066 | +1% | 1 | 1 | 0% | 1,253 | 9,181 | +633% | 0 | 0 | — |
case-06 | pass→pass | 10,869 | 6,964 | -36% | 1 | 1 | 0% | 2,070 | 9,300 | +349% | 0 | 0 | — |
case-07 | pass→pass | 5,267 | 8,376 | +59% | 1 | 1 | 0% | 977 | 9,673 | +890% | 0 | 0 | — |
case-08 | pass→pass | 9,802 | 12,726 | +30% | 1 | 1 | 0% | 1,931 | 10,205 | +428% | 0 | 0 | — |
case-09 | pass→pass | 13,107 | 9,611 | -27% | 1 | 1 | 0% | 2,590 | 9,654 | +273% | 0 | 0 | — |
case-10 | pass→pass | 15,112 | 11,742 | -22% | 1 | 1 | 0% | 2,706 | 10,142 | +275% | 0 | 0 | — |
case-11 | fail→pass | 6,318 | 12,781 | +102% | 1 | 1 | 0% | 1,203 | 10,201 | +748% | 0 | 0 | — |
case-12 | pass→pass | 19,557 | 16,244 | -17% | 1 | 1 | 0% | 3,509 | 10,984 | +213% | 0 | 0 | — |
case-13 | pass→pass | 9,945 | 11,890 | +20% | 1 | 1 | 0% | 1,831 | 9,993 | +446% | 0 | 0 | — |
case-14 | pass→pass | 13,645 | 12,245 | -10% | 1 | 1 | 0% | 2,981 | 10,355 | +247% | 0 | 0 | — |
case-15 | pass→pass | 10,835 | 7,652 | -29% | 1 | 1 | 0% | 2,001 | 9,374 | +368% | 0 | 0 | — |
case-16 | pass→pass | 7,445 | 7,942 | +7% | 1 | 1 | 0% | 1,295 | 9,265 | +615% | 0 | 0 | — |
case-17 | pass→pass | 2,685 | 4,529 | +69% | 1 | 1 | 0% | 531 | 8,601 | +1520% | 0 | 0 | — |
case-18 | pass→pass | 7,014 | 7,604 | +8% | 1 | 1 | 0% | 1,335 | 9,140 | +585% | 0 | 0 | — |
case-19 | pass→pass | 5,507 | 5,727 | +4% | 1 | 1 | 0% | 1,041 | 8,964 | +761% | 0 | 0 | — |
case-20 | fail→fail | 18,153 | 14,862 | -18% | 1 | 1 | 0% | 4,160 | 11,101 | +167% | 0 | 0 | — |
case-21 | fail→fail | 25,950 | 16,344 | -37% | 1 | 1 | 0% | 5,012 | 11,170 | +123% | 0 | 0 | — |
case-22 | fail→pass | 17,877 | 12,354 | -31% | 1 | 1 | 0% | 3,505 | 10,111 | +188% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +14 percentage points is the difference between those two pass rates over the 22 comparable cases. 1 case got worse with the skill loaded, and it is included in that figure.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.