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 > 100

Race 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)
Use case guides →Feature comparison →Valkey vs Redis →