What is Object Caching?

A typical web page asks the database the same questions over and over. What are this site's settings? What's in the navigation menu? What are the ten newest posts? Who is this logged-in user? The answers rarely change, but without a cache, every page view asks again, and the database does the same work thousands of times an hour.

Object caching keeps those answers in memory after the first time. The next request gets them from RAM in well under a millisecond, and the database gets to spend its time on questions that are actually new.

How it works

The common pattern is called cache-aside, and it's simple:

  1. The application needs some data. It asks the cache first, using a key like user:4182 or menu:main.
  2. If the cache has it, that's a hit. Use it and you're done.
  3. If not, that's a miss. Query the database, build the result, store it in the cache with an expiry time, then use it.

The application decides what to cache and for how long. The cache itself is just a very fast, networked key-value store that forgets things when it runs out of memory or the time runs out.

If you run WordPress, this is what a "persistent object cache" plugin does. WordPress already caches objects within a single page load. The plugin keeps them in Redis or Memcached between page loads, which on a busy site can take most of the load off MySQL.

The three ways it goes wrong

There's an old line that the two hard problems in computer science are cache invalidation, naming things and off-by-one errors. The first one is the reason.

Stale data. You update a product price in the database, and the cache keeps serving the old one until the entry expires. The fix is to delete or update the cache entry whenever you write the underlying data, and to keep expiry times short enough that a missed invalidation heals itself. A cache that never expires is a second database nobody maintains.

The stampede. A popular entry expires, and five hundred requests miss at the same moment. All five hundred run the same expensive query at once, and the database falls over. That's the opposite of what the cache was for. The fixes: let one request rebuild the entry while the others wait or get the stale copy, add a little random jitter to expiry times so related keys don't all expire together, or refresh hot entries in the background before they expire.

The cache becomes load-bearing. It starts as an optimization. Two years later the database can't handle the traffic without it, and a cache restart takes the site down. That's fine if you plan for it, with replicas, a warm-up procedure and alerting on the hit rate. It's not fine if you find out at 3 a.m.

Redis and Memcached

These are the two classic choices.

Memcached was written by Brad Fitzpatrick in 2003 for LiveJournal. It does one thing: a big, multi-threaded, in-memory hash table of strings with expiry times. No persistence, no replication, no data types. That simplicity is the point. It's fast, it uses memory efficiently, and there's almost nothing to configure. If all you need is a cache, it's a good one.

Redis was written by Salvatore Sanfilippo in 2009, and it's much more than a cache. Its values can be lists, sets, sorted sets, hashes, streams and more, with atomic operations on all of them. That makes it useful as a queue, a rate limiter, a session store, a leaderboard or a lock service. It can persist to disk and replicate to other nodes. For most applications that want a cache and also some of those things, Redis became the default.

Which to choose:

  • Pure page and query caching at high volume: Memcached is simpler and uses memory a little more efficiently.
  • Sessions, queues, counters or anything you'd be upset to lose on restart: Redis or one of its forks.
  • WordPress and most frameworks: either works well. Use whichever your hosting stack already knows.

And now Valkey

This spring changed the Redis half of that answer. In March, Redis Ltd. moved Redis from the BSD license to a pair of source-available licenses that bar cloud providers from offering it as a service. Within a week, a group of longtime Redis contributors, backed by AWS, Google Cloud, Oracle and others, forked the last BSD-licensed release as Valkey, under the Linux Foundation. Its first release went out in April.

For now Valkey is a drop-in replacement: same protocol, same commands, same clients. Linux distributions are starting to package it in place of Redis, and the cloud providers backing it have said they'll offer it as a managed service. If you're self-hosting a cache, there's no reason to deploy the source-available Redis over the open source fork. I wrote more about the license side in Free as in Freedom.

Running one safely

A few rules that save a lot of grief:

  • Never expose it to the internet. Bind to localhost or a private network. Exposed Redis instances have been mass-exploited for years, often by attackers using its own configuration commands to write SSH keys or cron jobs onto the host. Set a password or ACLs anyway.
  • Set a memory limit and an eviction policy. For a pure cache, maxmemory plus allkeys-lru means it evicts the least recently used keys instead of erroring when full.
  • Don't use one instance for cache and for data you can't lose. If the queue and the cache share memory, cache pressure will evict your queue.
  • Watch the hit rate. A cache with a 40 percent hit rate is mostly overhead. Either cache different things or cache them for longer.
  • Measure before and after. Caching the wrong thing adds a network round trip to every request and saves nothing.

Done well, an object cache is the cheapest performance upgrade most applications will ever get. Done carelessly, it's a second source of truth that's sometimes wrong.

Since then

Added October 2026. Valkey 8 shipped in September 2024 with much better multi-threaded I/O, and AWS and Google now sell it as a managed service. Redis added the AGPL as a license option with Redis 8 in May 2025, so it's open source again. Both are fine choices today, but the episode is a good reason to know who controls the software your stack depends on.