Hermes Wiki

Redis vs Memcached

Concept

Both Redis and Memcached are in-memory key-value stores built for the same core job — keep hot data close to RAM speed so the application doesn't pay a disk or network round-trip to a primary database on every read. Where they diverge is in how much they try to be beyond that: Memcached stays a pure cache — a multi-threaded, non-blocking daemon that stores unstructured byte blobs behind string keys and nothing else. Redis is a single-threaded (for data commands) in-memory data structure server that happens to be excellent as a cache but also supports rich types (hashes, lists, sets, sorted sets, streams), optional persistence to disk, replication, and pub/sub — closer to a lightweight database that can also cache than a cache that stayed a cache.

That architectural difference has a concrete consequence at the concurrency level. Memcached's multi-threaded design lets it use every core on a box to serve concurrent connections with minimal lock contention, which shows up as very predictable, very fast performance for simple get/set workloads at high connection counts. Redis processes one command at a time on its main thread (recent versions offload some network I/O and background work, but data commands still execute single-threaded) — this makes every command atomic by construction (no partial-update races to reason about) at the cost of a single slow command, like a large KEYS scan or an expensive Lua script, blocking every other client until it finishes.

Memory management follows the same split. Memcached uses a slab allocator: memory is pre-divided into fixed-size chunk classes, and a value gets rounded up to the nearest class. This avoids fragmentation but can waste real memory when values don't land close to a slab boundary. Redis uses a general-purpose allocator (jemalloc by default) that sizes allocations to the actual value, which is more memory-efficient per key but more prone to fragmentation over the lifetime of a long-running process under a churny key/value size distribution.

Tradeoffs

Dimension Memcached Redis
Concurrency model Multi-threaded, scales across cores for raw throughput Single-threaded for data commands — atomic by default, one slow command blocks all clients
Data model Flat key → byte-blob string only Strings, hashes, lists, sets, sorted sets, streams — supports structured operations server-side
Persistence None — a restart is a total cache loss Optional RDB snapshots and/or AOF command logging — can survive a restart
Memory efficiency Slab allocator: fast, low fragmentation, but rounds values up to fixed size classes jemalloc: tighter per-value fit, but can fragment over time under mixed value sizes
Operational surface Minimal — cache only, nothing else to run Broader — can also serve as a lightweight message broker (pub/sub, streams) or primary store for some workloads, which is a feature and a temptation

Neither is strictly better; they encode different bets about what a cache should be. Memcached bets that a cache should do exactly one thing extremely well and nothing else, with no state to lose and no single-threaded bottleneck. Redis bets that most teams end up wanting more than a flat get/set cache — atomic increments for counters, list operations for a queue, expiring hashes for session objects — and that the single-threaded model's atomicity guarantee is worth more than raw multi-core throughput for most cache-sized workloads.

When to use / when not to

  • Reach for Memcached when the need is genuinely a flat, ephemeral cache at very high throughput and connection concurrency — HTML fragment caching, session tokens, computed values with no need for structure — and losing everything on a restart is fully acceptable (the source of truth is always a fast rebuild away).
  • Reach for Redis when the cached data has real structure worth operating on server-side (a sorted leaderboard, a rate-limit counter needing atomic increment, a per-user list), when the workload benefits from Redis's broader primitives (pub/sub for cache invalidation events, TTL-per-field), or when some durability across restarts matters even for "just a cache."
  • Don't pick Redis by default without checking whether the single-threaded model is a real constraint for the workload — a hot key under heavy write contention, or an accidental expensive command in the same command stream, degrades every other client's latency in a way Memcached's multi-threaded model doesn't.
  • Don't add Redis's persistence or replication features to a workload that's genuinely just a disposable cache — that machinery adds operational surface (backup/restore procedures, replication lag to reason about) for a guarantee the workload doesn't need.

Common pitfall

Treating "cache" as one undifferentiated decision and picking whichever tool the team already knows, rather than checking whether the workload needs Redis's data structures or durability. The failure mode runs both directions: teams that reach for Redis purely out of familiarity end up running persistence and replication they never needed, paying the operational cost of a stateful service for a workload that was always fine to lose on restart; teams that reach for Memcached purely for its throughput reputation end up building atomic-counter or list logic in application code with race conditions that Redis would have handled server-side for free. The right question is what the cached data actually needs to do, not which tool is more familiar or which benchmark looked better.

Engineering Lens

The Redis-vs-Memcached decision is rarely really about raw cache throughput — most workloads never get close to either tool's ceiling. It's about how much non-cache functionality a team is willing to let creep into "the cache." Redis's rich data structures make it tempting to lean on it for things a cache was never meant to be responsible for (a primary data store, a message queue, a distributed lock service), and each of those uses raises the cost of losing that instance from "warm the cache" to "we lost data." The strong answer in a design review isn't which tool was picked — it's whether the team can say, precisely, what happens to correctness if that cache instance disappears right now, and whether that answer is still "nothing, we just get some cold-cache latency for a bit" regardless of which tool ended up in the diagram.

Sources

Hermes Wiki