Table of contents of the article:
When discussing website speed, one of the first topics that almost always comes up is Web Cache . The reason is simple: avoiding regenerating a page from scratch for each request drastically reduces the work required on the server side and, consequently, delivers content to the user much faster.
The underlying principle is relatively intuitive. When a dynamic CMS like WordPress generates a page, it can be forced to execute PHP code, query the database, load configurations, process plugins, retrieve information, and finally assemble the HTML document to send to the browser. If the resulting page is cached, many subsequent requests can bypass much of this processing and directly receive a ready-made copy.
Over the years, this concept has become accessible to a non-technical audience. Today, there are servers and stacks that integrate caching systems, solutions like LiteSpeed , WordPress plugins like WP Rocket, FlyingPress , and numerous other tools that allow you to achieve interesting results without necessarily having to know the ins and outs of how a reverse proxy works.
At the other extreme, we find technologies like Varnish (our preferred choice), which have historically been widely used in enterprise environments and infrastructures where extremely precise control of caching policies, content invalidation, and request behavior is required.
All very nice. But there's a problem.
Having a web cache configured does not automatically mean having a consistently fast site.
And this is precisely where we need to stop looking only at the loading time of a single URL and start thinking about a much more significant metric: how many requests actually manage to find the cached content during normal site navigation?
A very fast page does not mean having a fast site
One of the most common mistakes in performance evaluation is to take a page, open it a few times, test it with a testing tool, and conclude that the caching system is working properly.
Maybe the homepage responds very quickly. A product page does too. A category page seems perfect.
Then you really start sailing.
You open another product and the response takes significantly longer. You move on to the next category and it speeds up again. You open an article and it slows down again. You go back, enter another section, and suddenly everything seems fast again.
The result is what we might call stop-and-go browsing : some pages appear instantaneous, others behave as if the cache didn't exist.
From a technical standpoint, it is perfectly possible that this is exactly the case.
When a request finds a cached copy of the page, we typically have a cache HIT . The server can serve the content without having to completely rebuild the page through the application.
When that copy isn't available, we have a MISS . The request must then reach the lower levels of the stack and, depending on the architecture, may involve PHP processing, SQL queries, calls to external services, and everything else normally needed to generate that particular page.
And that's why the really interesting data isn't simply knowing whether the cache is active.
It is important to know its HIT Ratio , that is, the proportion of requests that can be satisfied directly from the cache compared to those that have to go through the backend again.
A blazing fast cache with a low HIT ratio can produce a worse user experience than a properly sized cache designed to maintain a consistently high HIT ratio.
Benchmarking on a single URL can only tell half the story or even less.
The problem is particularly evident when using synthetic benchmarks.
Suppose we test the same page ten times. On the first request, the system generates the content and caches it. The next nine requests find the page already available.
The result may seem excellent.
But a real user doesn't visit the same URL ten times in a row.
A user enters the homepage, opens a category, visits a product, returns to the category, applies a filter, opens a second product, reads an information page, and continues browsing.
On an editorial site, you might go from the homepage to an article, then to a related feature, then to a category or content published months earlier.
It is in this scenario that the true quality of the caching strategy emerges.
If only the most visited pages are cached while a large portion of the so-called long tail URLs continually require regeneration, the actual experience may be very different from that shown by the benchmark performed on the homepage.
The point is not to get a screenshot with an exceptional response time.
The point is to make most real-world navigation behave in a consistent, predictable way.
The problem of complete cache purges
One reason why the HIT Ratio can suddenly drop is the way some systems handle cache invalidation.
In certain configurations, a relatively common event can cause a very large portion of the cache, or even its entire contents, to be erased.
This can happen, for example, following a plugin update, changing some settings, publishing content, administrative interventions or simply when the user presses the classic “Clear all cache” button.
Since then, the site has formally still had a caching system, but the cache is empty.
Every URL requested for the first time then becomes a MISS.
The homepage is being refreshed. The first product is being refreshed. The first category is being refreshed. The second product is being refreshed. An old article is being refreshed.
As users browse, the cache gradually fills up again. Meanwhile, however, visitors themselves pay the cost of rebuilding it.
This is a particularly tricky situation because, after a few minutes or hours, the most popular pages will be available in the cache again, and a cursory check might lead one to believe that everything is working perfectly.
The problem persists on less frequented URLs and reappears again after the next purge.
Cache warm-up: why we try to fill the cache before users do
One of the techniques used to limit this behavior is the so-called cache warm-up.
The concept is simple: instead of waiting for the first visitor to request a page that isn't already in the cache, an automatic process preemptively visits the site's URLs and generates copies.
In theory, it's an elegant solution.
The cache is cleared, the warm-up process starts, and the pages are gradually rebuilt before users arrive.
The problem arises when you move from a small site with a few hundred URLs to a portal, magazine, or e-commerce site with tens or hundreds of thousands of pages, if not millions.
Imagine a site with a million potentially memorable URLs. A complete warm-up requires a huge number of requests, and most importantly, every page that isn't yet available must actually be generated by the backend.
This means CPU consumption, database usage, I/O, memory, PHP processes, and time.
In practice, a carelessly performed warm-up risks paradoxically behaving like a small stress test launched against your site.
And there's another problem: while the crawler in charge of warming up is rebuilding the pages, users continue to browse.
If the process takes a long time to cover the entire site, a significant portion of the URLs will still be discovered by real visitors first.
A cache must be sized for the site it is intended to serve.
This is where systems expertise comes in.
Installing a cache system is relatively simple. Designing a cache that's adequate for the volume, type of content, and traffic of a site is another matter entirely.
A cache that needs to manage a few thousand pages has completely different needs than an e-commerce site with hundreds of thousands of products, filters, categories, and variants.
We need to consider how much space to reserve for objects, what criteria to use to store them, how long to keep them available, which requests should be excluded and, above all, how to prevent less useful objects from continually pushing truly important ones out of the cache.
One mistake we encounter, for example, is using valuable application cache or page cache resources to store very large static files like images and videos.
This doesn't mean that images, CSS, JavaScript, or other assets shouldn't be stored somewhere. On the contrary, there are very efficient specific mechanisms for these resources: browser cache, web server cache, CDN, and object storage are examples of layers that can handle this.
The point is to avoid indiscriminately filling a space designed to store valuable items with files that could be more appropriately managed elsewhere.
On very large sites, the actual cache capacity and the policy for retaining or removing objects become integral to performance.
The real problem of intermittent navigation in e-commerce
On a blog, an occasionally slow page can be annoying.
On an e-commerce site it can become much more serious.
When a user is comparing products, colors, models, features, or prices, they tend to make many consecutive navigations. The perceived speed therefore doesn't depend on the loading of a single landing page, but on the continuity of the entire session.
A category that responds immediately, followed by a slow product, then another fast product, and then another wait creates a feeling of instability.
The user is unaware that behind the scenes some requests are HIT and others MISS.
He simply perceives that “the site is sometimes fast and sometimes not”.
And it's one of the most frustrating experiences because it makes every click unpredictable.
In a purchasing journey, this friction can compound with other small uncertainties and contribute to abandonment of the browsing or conversion process. An e-commerce site should instead strive to offer as consistent a response as possible throughout the catalog exploration.
TTFB, LCP and Core Web Vitals: why continuity matters
Caching a page has a particularly noticeable effect on the Time To First Byte, or TTFB , which is the time it takes for the browser to start receiving the requested response.
It's important to note that TTFB is not a Core Web Vital in itself . However, it comes early in the page loading chain: if the HTML document takes a long time to be returned, the browser will also take longer to discover and process many of the resources needed for display.
As a result, a high TTFB can impact subsequent metrics, including Largest Contentful Paint (LCP).
And it is once again the discontinuous behavior that is interesting.
Having an excellent TTFB on the homepage already stored is not enough if a significant portion of real navigation must continually reach a much slower backend.
For this reason, when we analyze an infrastructure, we're not just interested in knowing how fast the best possible HIT is . We're interested in understanding how often that HIT actually occurs.
Our approach: invalidate the content without passing the problem on to the first visitor
At Managed Server, we have developed a different approach to managing these scenarios.
The goal is to prevent a normal update or cleanup operation from suddenly turning thousands of fast URLs into just as many slow requests.
The logic is to separate the moment when a piece of content is considered to be updated from the moment when its last usable copy is actually abandoned.
When a page needs to be regenerated, the system can continue to use a previously stored representation through an intermediate layer. In the meantime, a new version is produced that will replace the previous one.
In other words, instead of having this sequence:
- clear page from cache;
- arrival of the first user;
- waiting for PHP generation and database queries;
- creating new cache;
- answer finally available;
We can ensure that the user continues to receive an immediately serviceable copy while the content is updated behind the scenes.
The practical result is important because the refresh process is no longer automatically transformed into a slowdown perceptible to the visitor.
This principle can also be applied when a very extensive cache purge is required: the architecture avoids, as far as possible, that the logical purge coincides with the immediate destruction of the last response ready to be provided.
The advantage is not to have the speed record, but to eliminate the peaks of slowness
This introduces a change of perspective.
In the performance world, we often tend to look for the lowest possible number: 100 milliseconds, 80 milliseconds, 50 milliseconds.
But for a user, it can be much more important to have twenty consecutive pages that respond uniformly than to have ten instantaneous pages alternating with ten others that require much longer waits.
Real performance is also predictability.
An effective caching architecture should seek not only to lower the mean, but also to reduce the gap between the best and worst behavior.
This means maintaining a more stable TTFB while browsing, reducing the number of requests that suddenly fall back to the application server, and limiting load spikes that occur after massive invalidations.
The benefit is therefore double.
On the one hand, the user experiences a more consistent and responsive site. On the other, the backend is protected from those waves of simultaneous regenerations that can occur at just the worst time, such as after a cache change while the site is receiving heavy traffic.
A high HIT Ratio also protects PHP and databases
Web Cache isn't just for quickly displaying a page.
It also serves to avoid unnecessary work on the underlying infrastructure.
Any request that can be satisfied with an adequate level of caching is potentially a request that should not go to WordPress, PHP, or the database.
When the HIT Ratio decreases, however, the backend has to absorb a greater amount of traffic.
This phenomenon can create a vicious circle.
The cache is flushed. MISSES increase. The number of PHP processes increases. Database queries increase. The server uses more resources. Dynamic pages become even slower just as the system is trying to rebuild the cache.
On high-traffic sites, the problem can be particularly acute because multiple users may simultaneously request items that have not yet been rebuilt.
This is why a professional strategy must concern itself not only with how to create the cache , but also with how to manage its lifecycle, refresh, invalidation and reconstruction.
Crawlers also benefit from a consistently responsive infrastructure
Consistent performance also affects search engine crawlers.
A site with a large number of URLs may receive continuous requests from Googlebot and other crawlers. If a significant portion of these requests can be served quickly without heavily involving the backend, the infrastructure can more easily support the crawling activity.
Google itself takes into account the server's ability to respond to requests: when an infrastructure slows down significantly or experiences errors, crawlers can reduce the pressure to avoid overloading it.
This does not mean that a better cache automatically guarantees better rankings, nor that increasing crawl speed is a ranking factor in itself.
However, it does mean that a fast, stable server capable of handling crawling without saturating creates better technical conditions for efficient scanning , especially on very large sites.
Don't just ask yourself, "Do I have cache?", ask yourself, "How often am I using it?"
Web Cache remains one of the most important tools for improving the performance of a dynamic site.
But the mere presence of LiteSpeed, Varnish, a WordPress plugin, or any other system isn’t enough to determine whether the strategy is actually working.
The behavior of the entire site needs to be observed.
We need to understand what happens after a purge.
You need to check how long it takes to reconstruct the URLs.
You need to evaluate whether the cache has enough space for the actual volume of content and whether its retention policies are compatible with the project.
Above all, one should observe the HIT Ratio in real traffic.
Because the important result is not to show that a page can be extremely fast when all conditions are favorable.
The bottom line is making sure that that speed is available on most pages, most of the time.
Web Cache is nice. Hit Ratio is better.
A well-configured web cache can dramatically improve the performance of WordPress, WooCommerce, and any dynamic application. However, as your site grows, simply enabling a cache is no longer the issue.
The problem becomes keeping it effective over time.
A system that is completely gutted with every change and progressively rebuilt on the backs of users can achieve spectacular benchmarks on already heated URLs while simultaneously offering a terrible experience on the rest of the site.
This is why at Managed Server we prefer to think in terms of continuity, HIT percentage and backend protection.
By using an architecture that maintains a usable intermediate copy while content is regenerated, we can prevent normal cache refreshes from suddenly producing stuttering navigation.
This means more consistent TTFB, fewer expensive requests to PHP and databases, fewer load spikes, a better browsing experience, and more favorable conditions for loading metrics and crawler activity as well.
Because a cache shouldn't be judged solely by how fast it is when hit.
It should be judged above all by how often it manages to be ready.