Software

How Caching Works: Cache Strategies Explained with Redis vs Memcached

Talha AslanTalha Aslan 18 min read 1 views

Caching means serving frequently requested data from a fast layer instead of hitting a slow source every time. I have managed web projects since 2012. In most slow sites I audit, the problem is not the code itself. It is an architecture that runs the same query thousands of times. This guide covers caching strategies, TTL, invalidation and the real differences between Redis and Memcached.

I wrote it from a developer's point of view, but I kept it plain enough for project owners. You can find more technical articles in the software category.

What is caching and why do applications need it?

Caching is the practice of storing the result of a query or computation in fast memory for a limited time, so later requests can reuse it without rebuilding it. The goal is to reduce load on slow resources such as databases, external APIs or heavy calculations, and to cut response time.

The logic is simple. RAM is far faster than a disk read or a network round trip. So you keep data that people read often but that rarely changes, such as product lists, category menus or exchange rates, in memory. As a result, the database only works when you truly need fresh data.

However, caching is never free. The moment you keep data in two places, you face a new question: which copy is correct? Most of this article is about managing that question. First I cover the layers, then the strategies, and finally the two most popular tools.

Where does a cache live in a typical web stack?

A web request passes through several cache layers on its way from the browser to the database. Each layer also solves a different problem. Therefore you cannot manage all of them with the same rules.

  • Browser cache: keeps CSS, JavaScript and images on the user's device. You control it with the Cache-Control header.
  • CDN and reverse proxy: store static files, and sometimes full HTML pages, on servers close to the user.
  • Application cache: a server such as Redis or Memcached holds query results, sessions and computed objects.
  • In-process cache: small dictionaries inside the application's own memory. It is the fastest option, but servers cannot share it.
  • Database cache: the database's own buffer pool keeps hot pages in memory.

For the HTTP side, the web.dev guide to the HTTP cache gives a clear summary. In this article I focus on the application layer, which means the world of Redis and Memcached.

What do cache hit and cache miss mean?

A hit happens when the requested data already sits in the cache. The application returns it straight from memory. A miss happens when the data is not there. In that case the application goes to the source, reads the value and usually writes it into the cache as well.

The hit ratio shows what share of all reads the cache serves. Example calculation: if 900 of 1,000 reads come from the cache, your hit ratio is 90 percent. The remaining 100 requests reach the database.

Still, do not treat the hit ratio as the only goal. You can push it up with a very long TTL. Yet you would then show stale data to your users. The real measure is whether you serve correct data with acceptable latency.

You should also know the idea of a cold cache. After a restart or a new deployment, the cache is empty. In the first minutes almost every request misses. For that reason, busy systems often run a small script that preloads the most popular keys right after a release. People call this cache warming.

How does the cache-aside pattern work?

Cache-aside, also called lazy loading, is the most common caching pattern. The application treats the cache as a side store and keeps full control. The AWS whitepaper on caching patterns also describes it as the baseline approach.

  1. First, the application asks the cache for a key.
  2. If the value exists, it returns it at once.
  3. If not, it then queries the database.
  4. It writes the result into the cache with a TTL.
  5. Finally, it returns the result to the user.

The main advantage is that you only cache data that someone actually requested. In addition, if the cache server goes down, the application slows down but keeps working. That resilience makes cache-aside my first choice. The downside is the extra round trips on every miss. You also have to clear stale keys yourself when data changes.

What is the difference between read-through and write-through?

In a read-through setup the application talks only to the cache. When a key is missing, the cache layer loads the value from the source on its own. In other words, the miss logic moves out of your code and into a library or a caching provider.

Write-through handles the write side. When the application updates a record, it writes the new value to the database and to the cache in the same operation. As a result, the cache always stays current and reads hit on the first try.

On the other hand, write-through makes every write a little slower, because you write to two places. It also fills the cache with data that nobody may ever read. So I usually reserve write-through for data that people read often and that must appear instantly, such as stock levels or prices.

You can also combine the two families. Many of my projects use cache-aside for reads and write-through for a handful of critical records.

When does write-behind make sense?

Write-behind, also known as write-back, writes to the cache first. It then flushes changes to the database later, often in batches. For the user, writes feel very fast because nothing waits for the slow source.

However, this pattern carries a serious risk. If the cache server crashes before it flushes, you can lose those writes. Therefore I never use write-behind for payments, orders or invoices.

So where does it help? It fits data where approximate accuracy is enough and write volume is very high. Page view counters, like counts and analytics events are good examples. For instance, instead of writing to the database on every view, you increment a counter in memory and save it once per minute.

How should you choose a TTL?

TTL, or time to live, sets how many seconds a key stays in the cache. When it expires, the key disappears. The next read then refreshes the value from the source.

When I choose a TTL, I ask one question: how stale can this data get before the business suffers? The ranges below are a starting point based on field experience, not a guarantee. Measure your own traffic and adjust.

  • Category menus and site settings: hours.
  • Product details and blog lists: a few minutes up to an hour.
  • Stock and prices: seconds, or event based clearing.
  • Session data: as long as the user session lasts.

One more tip. If thousands of keys share the exact same TTL, they all expire at the same moment. That creates a sudden load spike. So add a small random offset, often called jitter, to every TTL.

Why is cache invalidation so hard?

Invalidation means removing or updating the stale copy when the source data changes. It is hard because one piece of data often spreads across many cache keys.

Take a product price change. It does not only affect the product detail key. The category list, search results, a campaign page and the home page showcase may all carry that price. Miss one, and users see two different prices.

In practice I rely on three approaches:

  • Event based deletion: when a record changes, your code deletes the related keys explicitly.
  • Versioned keys: you add a version number to the key. When data changes, you bump the version, and old keys simply expire.
  • Short TTL: if perfect freshness does not matter, you leave invalidation to the TTL alone.

In short, for every key you add, write down who deletes it and when. Do this before the key goes live, not after the first bug report.

What is a cache stampede and how do you prevent it?

A cache stampede happens when a popular key expires and hundreds of requests miss at the same moment. They all hit the database together. The database slows down, more requests pile up, and the whole system can stall.

You usually see it at peak times, such as the start of a sale. Fortunately, the fixes are well known:

  • Use a lock: on a miss, only one request rebuilds the value. The others wait briefly or get the old value.
  • Add TTL jitter: keys stop expiring in the same second.
  • Refresh early: a background job renews the value shortly before it expires.
  • Serve stale while revalidating: users get the old value for a moment while a worker prepares the new one.

In Redis you can build a simple lock with the SET command and its NX and EX options. Only the first process gets the lock, and the lock expires on its own after a set time.

What happens when the cache runs out of memory?

A cache runs on limited RAM. When memory fills up, it must remove some keys to make room. This process is eviction, and the eviction policy decides which keys go.

In Redis you control this with the maxmemory and maxmemory-policy settings. According to the Redis eviction documentation, the default policy is noeviction. That means Redis does not delete anything when memory is full. Instead it returns errors on new writes. If you use Redis as a pure cache, change this default.

  • allkeys-lru: removes the least recently used key. A good default for general caching.
  • allkeys-lfu: removes the least frequently used key.
  • volatile-lru and volatile-ttl: choose only among keys that have a TTL.
  • noeviction: deletes nothing and rejects writes.

Memcached, by contrast, evicts old items automatically with its own LRU logic. You do not need to pick a policy.

How does Redis work under the hood?

Redis is an in-memory data structure server built on a key value model. What sets it apart from a plain cache is that values can be rich data types, not just strings.

First, Redis supports strings, hashes, lists, sets, sorted sets and streams. For example, you can model a leaderboard with a sorted set, a job queue with a list and a user profile with a hash. That way the server handles sorting or counting in a single command.

Redis also offers persistence. RDB takes point in time snapshots at intervals. AOF appends every write command to a log file. Thanks to these, you can reload data from disk after a restart.

Command execution runs mainly on one main thread. Since Redis 6, extra threads can handle network I/O. Single threaded execution makes every command atomic. That said, one slow command, such as KEYS over a large keyspace, blocks every other client.

How do replication and clustering work in Redis?

Redis supports replication from one primary to one or more replicas. You can spread read traffic across replicas. With Sentinel, you also get automatic failover when the primary dies.

When your data no longer fits in one server's memory, Redis Cluster steps in. Specifically, it splits the keyspace into 16,384 hash slots and spreads those slots across nodes. This lets you scale horizontally over several machines.

You should also know about licensing. In 2024 Redis moved from the BSD license to a dual RSALv2 and SSPLv1 license. With Redis 8, it added an AGPLv3 option. After the change, the Linux Foundation launched Valkey, an open source fork. For enterprise projects, confirm which distribution you run together with your legal team.

How does Memcached work?

Memcached is a simple, multithreaded, in-memory key value store built only for caching. It does not interpret values. You hand it a blob of bytes, and it hands the same bytes back.

In addition, it manages memory in size classes called slabs. This reduces fragmentation. However, it can waste some space when your values vary widely in size. According to the Memcached wiki, the default maximum item size is 1 MB and keys can be up to 250 bytes. You can raise the item limit with a startup flag.

Memcached offers no persistence and no built-in replication. Distribution across several servers usually happens on the client side through consistent hashing. In other words, the client library decides which server holds which key.

That simplicity is a strength. With fewer settings, there is less room for misconfiguration. Its threads also spread load well on multicore servers.

Watch out for one trap. If you set an expiry longer than 30 days, Memcached reads the number as a Unix timestamp, not as seconds. A wrong value can make the key expire immediately.

Redis vs Memcached: what are the key differences?

In practice, both tools run in memory and deliver similar speed for simple caching jobs. The real difference lies in feature scope and operating model. The table below sums up the main points.

FeatureRedisMemcached
Data typesStrings, hashes, lists, sets, sorted sets, streamsByte strings only
PersistenceRDB and AOFNone
ReplicationBuilt in, failover with SentinelNot built in
ScalingRedis Cluster, 16,384 slotsClient side consistent hashing
ThreadingOne main thread, extra I/O threadsMultithreaded
EvictionConfigurable policy, default noevictionAutomatic LRU
ExtrasPub/sub, Lua scripts, transactionsNone, simple by design
LicenseRSALv2, SSPLv1 or AGPLv3BSD

Put simply, Redis is a Swiss army knife, while Memcached is a single sharp blade.

When should you pick Redis and when Memcached?

I start most new projects with Redis. The reason is not raw speed. It is that one tool covers caching, session storage, queues and rate limiting.

Pick Redis if you need data structures such as sorted lists or counters. Also pick it if data must survive a restart, or if you plan real time messaging with pub/sub.

Memcached makes sense if you only need a simple, temporary object cache. It also fits when you want maximum throughput from one multicore server, or when your stack already runs on it. For instance, I would not replace a working Memcached setup in an older PHP project just to follow a trend.

Finally, consider your team's skills. A simple tool you know well is safer than a powerful one you half understand.

In the cloud, managed services such as AWS ElastiCache offer both Redis compatible engines and Memcached. The provider then handles backups, patches and failover. For small projects, a single Redis instance on the same server is often enough.

What is the difference between full page caching and object caching?

Full page caching stores the entire HTML output and sends it as is to the next visitor. Object caching stores pieces of a page instead, such as a query result or a computed menu. The page then reassembles from those pieces on each request.

Full page caching gives the biggest speed gain, because your application code barely runs. However, it is risky on pages with personal parts, such as a cart, a logged in user name or custom pricing. So I apply it to blog posts, company pages and campaign landing pages.

Object caching is more flexible. Even on a personalised page, you still read shared parts, such as the category tree, from the cache. In practice you combine both: full pages for anonymous visitors, object caching for logged in users.

Should you store sessions in a cache?

Yes, in most cases, and it is one of the most common uses of Redis. With several application servers, file based sessions break. Each request may land on a different server, and the user loses the session. A shared Redis server solves that.

Still, think differently here than with pure caching. When a session key disappears, the user gets logged out. So you do not want your eviction policy to delete those keys at random. I usually keep sessions in a separate Redis instance or a separate logical database.

Also align the session TTL with your security policy. A very long session lets a stolen cookie work for a long time.

How do you secure your caching layer?

Cache servers aim for speed, so security can take a back seat in default setups. An open Redis or Memcached server without a password invites attackers to read data or abuse the machine.

  • Bind the cache server to a private network or localhost only.
  • In Redis, set a password and use ACLs for per user permissions.
  • Close the port to the outside world in your firewall.
  • Turn on TLS if clients connect over a network.
  • Never write card data or passwords into the cache.

In short, treat the caching layer as seriously as the database. It holds a copy of the same data.

When is caching unnecessary?

That said, not every project needs a cache. Take a small business site with a few hundred daily visits and queries that already return in milliseconds. There, caching adds a new source of bugs without real benefit.

Also, requests that produce a unique result every time, such as personal report queries, gain little. Their hit ratio stays low. Fix database indexes and query design first. A missing index often brings a far larger gain than any cache.

My rule is simple. I add caching after I measure and find the bottleneck, never before.

How should you design cache keys?

Key design looks trivial at first, because keys are just strings. Yet how easily you can invalidate depends on it. Above all, a good key is readable, unique and predictable.

In practice, I usually follow an "app:entity:id:version" pattern. For example, "shop:product:4521:v3" tells you at a glance what it holds. If content varies by language or currency, add that to the key too. Otherwise a German visitor may receive the English page.

Also avoid pattern searches with KEYS in production, because it blocks the server on large datasets. If you need bulk deletion, use SCAN or versioned keys instead. And never store user specific data under a shared key. It is the quietest way to leak personal data.

How does caching affect site speed and SEO?

Caching directly shortens time to first byte, or TTFB. The server no longer rebuilds the page from the database on every request. So HTML leaves earlier, and the browser starts rendering earlier.

Google looks at Core Web Vitals as part of page experience, and a slow server response hurts LCP. I explain this link in detail in my article on how site speed affects SEO. To measure the effect of a change, follow the steps in my Lighthouse performance test guide.

Caching also matters for search engine crawlers. A fast server lets a crawler visit more pages in the same time. For the rest of the technical side, see my technical SEO tips.

What are the most common caching mistakes?

I see the same mistakes again and again in the projects I audit. Most of them come from missing planning, not from technical limits.

  1. Caching everything: rarely read data fills memory and pushes out useful keys.
  2. Skipping the TTL: keys without expiry slowly fill up with stale data.
  3. Keeping the default eviction policy: Redis starts rejecting writes when memory is full.
  4. Putting personal pages in a shared cache: one user's cart may appear for another user.
  5. Treating the cache as the primary store: without persistence, critical data in the cache alone can vanish.
  6. Optimising without measuring: adding a cache before you find the slow query hides the problem instead of solving it.

On online stores I take the last point very seriously. I make these infrastructure decisions based on data during ecommerce consulting projects.

How do you measure cache performance?

A cache you do not measure is a cache you cannot trust. So I recommend tracking at least four metrics.

  • Hit ratio: in Redis, calculate it from keyspace_hits and keyspace_misses in INFO stats.
  • Memory usage: shows how close you are to maxmemory. Running at the limit all the time raises evictions.
  • Evictions: if evicted_keys grows fast, memory is too small or you store useless data.
  • Latency: log response times for cached and uncached requests separately.

Also use the Redis SLOWLOG feature to spot slow commands. That way you catch the case where one heavy command stalls the whole system.

On the application side, tag and log each cache call. For example, once you see which key group misses most, you know whether to extend the TTL or fix an invalidation rule.

Where should you start with a caching strategy?

Start small with caching. First, find the five slowest and most frequent queries in your application. Most of the load usually comes from a few queries. Then apply cache-aside with a short TTL to those queries and watch the hit ratio.

Next, write down your invalidation rules. A table that maps each record change to the keys it clears keeps new developers from making mistakes. After that, add stampede protection and basic monitoring.

In larger architectures, the cache layer also relates to how you split the front end. I cover that in my article on micro frontend architecture. If you are building a new site, include caching decisions in the web design plan from day one. It costs far less than patching later. To check that your domain points to the right server, use the DNS lookup tool. To inspect redirect chains, try the redirect checker.

Frequently Asked Questions

Can caching replace a database?
No, caching cannot replace a database. A cache keeps a temporary copy of frequently read data in fast memory. The source of truth should always stay in the database. Redis does offer persistence. Even so, keeping orders, payments or user accounts only in a cache can lead to data loss that is hard to recover after a crash.
Is Redis faster than Memcached?
For simple key value reads, both tools perform at a similar speed, and most projects never notice a difference. Memcached uses many threads, so it makes good use of multiple cores on one server. Redis can still finish work faster overall, because rich data types let it do more in one command. Choose based on features rather than speed.
What TTL should I use?
There is no single correct TTL. You set it based on how stale the data may get. Hours for site settings, minutes for product lists and seconds for stock or prices make a sensible start. These ranges come from field experience and are not a guarantee. Then watch the hit ratio and user complaints, and adjust the value.
Can I combine cache-aside and write-through?
Yes, and in many projects this hybrid gives the best result. You use cache-aside for reads, so you only load data that someone requests. When a critical record changes, write-through refreshes the cache at once. That way you avoid filling memory with unused data while important values always stay current for every user.
Does caching directly improve SEO rankings?
Caching is not a ranking factor on its own. However, it shortens server response time and improves page speed. Faster pages help Core Web Vitals and the overall user experience. A fast server also lets search engine crawlers move through the site more efficiently. So the effect is indirect, and it never replaces content quality.
What is Valkey and can it replace Redis?
Valkey is an open source fork of Redis that started under the Linux Foundation after the 2024 license change. It grew from the Redis 7.2 codebase, so it stays largely compatible with core commands. Consider it if an open source license matters to you. Before switching, test your client library and cloud provider support in a staging environment.
#caching#Redis#Memcached#TTL#cache invalidation#software architecture#performance
Share:
Talha Aslan
Talha Aslan

Google Partner digital marketing expert. Hands-on with SEO, Google Ads, web design and e-commerce projects since 2012; every post here comes from that experience.

Next project

Let's talk about your project.

No middlemen, no layers: you talk directly to the expert doing the work. The first consultation is free, I listen to your goal and come back with a clear roadmap.

WhatsApp Call Now