Home / Code Samples
Redis vs Memcached: The Same Task, Side-by-Side
5 tasks with real code in Python/Node.js. Where Memcached cannot do it, the column says so. All code targets current versions: Redis 8.0, Memcached 1.6.x, Valkey 8.1.
1. Cache GET/SET with TTL
Memcached (pymemcache)
from pymemcache.client import base
c = base.Client(('localhost', 11211))
# Set with 60-second TTL
c.set('page:home', '<html>...', expire=60)
# Get
value = c.get('page:home')
# Delete
c.delete('page:home')Redis (redis-py)
import redis
r = redis.Redis(host='localhost', port=6379)
# Set with 60-second TTL
r.set('page:home', '<html>...', ex=60)
# Get
value = r.get('page:home')
# Delete
r.delete('page:home')Valkey (redis-py)
import redis
# Valkey is RESP-compatible: same client
r = redis.Redis(host='valkey-host', port=6379)
# Identical API to Redis
r.set('page:home', '<html>...', ex=60)
value = r.get('page:home')
r.delete('page:home')2. Atomic counter with TTL (rate limiter primitive)
Memcached — awkward
from pymemcache.client import base
c = base.Client(('localhost', 11211))
def rate_check(ip: str) -> bool:
key = f"rl:{ip}"
count = c.incr(key, 1)
if count is None:
# Race: two threads may both add on first hit
c.add(key, 1, expire=60)
return False
# WARNING: TTL NOT updated on incr
# You must track expiry separately
return count > 100Race condition on first hit. TTL not extended on incr. Fragile.
Redis / Valkey — atomic, correct
import redis, time
r = redis.Redis()
def rate_check(ip: str, limit=100, window=60) -> bool:
key = f"rl:{ip}:{int(time.time()) // window}"
count = r.incr(key)
if count == 1:
r.expire(key, window) # Set TTL on first hit
return count > limit
# INCR is atomic. Expire on first hit.
# No race conditions. No retry loops.
# Valkey: identical API.Atomic INCR. TTL set on first hit. No race conditions.
3. Hash field with per-field TTL (Redis 8.0)
Memcached
Not supported. Memcached does not have hashes. Approximate with per-field keys + manual TTL management.
Redis 8.0 (HEXPIRE)
# Redis 8.0: per-field TTL on hash HSET user:123 name "Ada" email "ada@x.com" auth_token "tok" # auth_token expires in 15 minutes HEXPIRE user:123 900 FIELDS 1 auth_token # name and email persist (no expiry) # Session: different fields, different lifetimes
Valkey 8.1
Hash field TTL (HEXPIRE) is in the Valkey roadmap but was not shipped in Valkey 8.1 (early 2026). Hashes supported; per-field TTL pending. Use whole-hash EXPIRE as a workaround.
4. Pub/sub fan-out
Memcached
Not supported. Memcached is a key-value cache only. For pub/sub, use Redis, Valkey, Kafka, or NATS.
Redis (ioredis, Node.js)
import Redis from 'ioredis';
const sub = new Redis();
const pub = new Redis();
sub.subscribe('chat:room1');
sub.on('message', (channel, msg) => {
console.log(`[${channel}] ${msg}`);
});
pub.publish('chat:room1', JSON.stringify({
user: 'ada',
text: 'hello',
ts: Date.now(),
}));Valkey (ioredis, identical)
import Redis from 'ioredis';
// Valkey: same RESP protocol, same client
const sub = new Redis({ host: 'valkey-host' });
const pub = new Redis({ host: 'valkey-host' });
sub.subscribe('chat:room1');
sub.on('message', (channel, msg) => {
console.log(`[${channel}] ${msg}`);
});
pub.publish('chat:room1', JSON.stringify({
user: 'ada',
text: 'hello',
ts: Date.now(),
}));5. Sorted-set leaderboard
Memcached
Not supported. Memcached has no sorted sets. Leaderboard requires application-side sorting: read all scores, sort in code, write back. O(N log N) in your app, not the cache.
Redis / Valkey (redis-py)
import redis
r = redis.Redis()
# Add / update scores — O(log N)
r.zadd('leaderboard', {
'player1': 1500,
'player2': 2200,
'player3': 1800,
})
# Top 10 — O(log N + 10)
top10 = r.zrevrange(
'leaderboard', 0, 9, withscores=True
)
# [('player2', 2200.0), ('player3', 1800.0), ...]
# Player rank — O(log N)
rank = r.zrevrank('leaderboard', 'player1')
# 0-indexed: 2 (third place)Valkey: identical API. Both support ZADD/ZREVRANGE/ZREVRANK.
Bonus: Redis 8.0 vector search
# Redis 8.0: vector similarity search (HNSW) # Add embeddings (3D example) VADD products VALUES 0.1 0.9 0.3 "product:101" VADD products VALUES 0.8 0.2 0.6 "product:102" VADD products VALUES 0.15 0.85 0.35 "product:103" # Find top 2 similar to a query vector VSIM products VALUES 0.12 0.88 0.32 COUNT 2 # -> "product:101", "product:103" # Memcached: not supported # Valkey 8.1: not yet shipped (early 2026)