Use when working with Valkey, Redis, or any Redis-compatible datastore. TRIGGER: code imports ioredis, redis, redis-py, valkey-py, go-redis, jedis, lettuce, or valkey-glide; Dockerfile/compose uses redis or valkey image; user mentions caching layer, session store, pub/sub, rate limiting with Redis/Valkey, streams, consumer groups, sorted sets, distributed locking, Redlock, ElastiCache, MemoryDB, Dragonfly, KeyDB, or any RESP-protocol store. DO NOT TRIGGER for general SQL databases, MongoDB, DynamoDB, Memcached (without Redis mention), or message brokers like RabbitMQ/Kafka unless explicitly compared to Redis/Valkey.
Valkey is a BSD-3 licensed fork of Redis 7.2.4, created March 2024 after Redis switched to RSALv2/SSPLv1. Maintained by Linux Foundation. Valkey 7.x/8.x are drop-in replacements for Redis ≤7.2.4—same protocol (RESP2/RESP3), same data formats, same client libraries. Valkey 8+ adds multi-threaded command execution. Redis 7.4+ diverges under source-available licensing. All patterns below apply to both unless noted.
Use valkey-server / valkey-cli as direct replacements for redis-server / redis-cli. Existing client libraries (ioredis, redis-py, go-redis, Jedis, Lettuce) work unchanged. Valkey-native clients: valkey-py, valkey-go, valkey-glide.
General-purpose: counters, serialized objects, flags.
SET user:1001:name "Alice" EX 3600 # set with 1-hour TTL
GET user:1001:name # => "Alice"
INCR request_count # => 1 (atomic increment)
MSET k1 "v1" k2 "v2" # multi-set (batch)
MGET k1 k2 # => ["v1", "v2"]
SETNX lock:order:42 "owner-abc" # set-if-not-exists (basic lock)
Use for objects. More memory-efficient than serialized JSON in a string when accessing individual fields.
HSET user:1001 name "Alice" email "[email protected]" plan "pro"
HGET user:1001 email # => "[email protected]"
HGETALL user:1001 # => {name: "Alice", email: "[email protected]", plan: "pro"}
HINCRBY user:1001 login_count 1 # atomic field increment
Ordered by insertion. Use for queues, recent-items, activity feeds.
LPUSH queue:emails "msg-1" "msg-2" # push left
RPOP queue:emails # pop right => "msg-1" (FIFO)
BRPOP queue:emails 5 # blocking pop, 5s timeout
LRANGE recent:posts 0 9 # last 10 items
LTRIM recent:posts 0 99 # cap at 100 entries
Unordered unique members. Use for tags, unique visitors, feature flags.
SADD online:users "u1" "u2" "u3"
SISMEMBER online:users "u2" # => 1 (true)
SINTER online:users premium:users # intersection
SCARD online:users # => 3 (cardinality)
Ordered by score. Use for leaderboards, priority queues, time-series indexes.
ZADD leaderboard 1500 "alice" 1200 "bob" 1800 "carol"
ZREVRANGE leaderboard 0 2 WITHSCORES # top 3 descending
# => ["carol", 1800, "alice", 1500, "bob", 1200]
ZRANGEBYSCORE leaderboard 1300 1600 # score range => ["alice"]
ZINCRBY leaderboard 100 "bob" # bump score atomically
ZRANK leaderboard "bob" # 0-based rank ascending
Append-only log. Use for event sourcing, message queues, audit trails.
XADD orders * product "widget" qty 3 # => "1700000000000-0" (auto ID)
XLEN orders # => 1
XRANGE orders - + # all entries
XREAD COUNT 10 BLOCK 2000 STREAMS orders 0 # read from start, block 2s
Probabilistic cardinality estimation. 12KB per key regardless of set size. 0.81% standard error.
PFADD unique:visitors "ip1" "ip2" "ip3"
PFCOUNT unique:visitors # => 3 (approximate)
PFMERGE daily:uv weekly:uv # merge counts
Bit-level operations on strings. Use for feature flags, bloom filters, daily active users.
SETBIT user:1001:features 0 1 # enable feature 0
GETBIT user:1001:features 0 # => 1
BITCOUNT active:2024-01-15 # count set bits
Geo-indexed data built on sorted sets.
GEOADD locations -122.4194 37.7749 "sf" -73.9857 40.7484 "nyc"
GEODIST locations "sf" "nyc" km # => "4139.4516"
GEOSEARCH locations FROMMEMBER "sf" BYRADIUS 500 km ASC
Use colon-delimited namespaces: {entity}:{id}:{field}. Keep keys short in high-volume scenarios.