Performance benchmarks are easy to manipulate.
A clean WordPress installation with a lightweight theme, no traffic, no third-party scripts and only a handful of active plugins can produce impressive numbers, but it tells us very little about how a caching plugin behaves on an actual production website.
For this comparison, we wanted something different.
We tested LiteSpeed Cache, WP Rocket and UltraCache on the same real WooCommerce website, running on the same production server, with the same content, theme, plugins and infrastructure.
The website belongs to a client, so its domain and identifying information are intentionally omitted. The identity of the store is irrelevant to the benchmark; the important part is the workload.
The tested installation consists of:
- WordPress 7.1
- WooCommerce 11.0.1
- 27 active plugins
- A customized Salient child theme
- Redis object caching
- Third-party analytics, advertising and marketing integrations
- A normal production WooCommerce frontend rather than a synthetic benchmark installation
The objective was not to make any competing plugin look bad. Each plugin was given its strongest legitimate, production-functional configuration. When an optimization caused a real compatibility problem, we fixed the minimum necessary issue rather than deliberately disabling the feature and benchmarking a weaker setup.
That also means the products were allowed to use the capabilities genuinely available to them. LiteSpeed Cache was tested on LiteSpeed Enterprise with native LSAPI/LSPHP. WP Rocket was tested with RocketCDN active because it was available as part of the WP Rocket setup used here. UltraCache was tested on the same origin server and WordPress installation.
This is therefore not a laboratory comparison in which every internal mechanism is forced to be identical. It is a real-world comparison of the best production configuration we could obtain from each product, with the differences disclosed rather than hidden.
Test Server
All three plugins were benchmarked on exactly the same server.
| Component | Configuration |
|---|---|
| Operating System | CloudLinux 7.9 |
| Kernel | 3.10.0-962.3.2.lve1.5.88.el7.x86_64 |
| Control Panel | cPanel/WHM 110.0.139 |
| Web Server | LiteSpeed Enterprise 6.3.5 |
| PHP execution | LSAPI / LSPHP |
| PHP | EA-PHP 8.3 |
| PHP-FPM | Disabled |
| CPU | Intel Xeon E-2236 @ 3.40 GHz |
| CPU topology | 6 physical cores / 12 threads |
| RAM | 32 GB |
| Database | MariaDB 10.6.19 |
| Object Cache | Redis 6.2.6 |
LiteSpeed Cache was therefore tested on the server stack for which it is specifically designed. It was not disadvantaged by running on Apache, nginx or a non-LiteSpeed PHP execution path.
WP Rocket and UltraCache were then tested on the exact same infrastructure.
Client-Side Test Environment
All Lighthouse tests were performed from the same desktop computer using the same Internet connection, approximately 80 Mbps download / 20 Mbps upload.
Testing was performed directly inside Google Chrome using the built-in DevTools Lighthouse panel.
- Google Chrome / Chromium 152
- Lighthouse 13.4.1
- Desktop emulation
- Initial page-load tests
- Identical Lighthouse throttling settings for every run
Using Lighthouse inside Chrome kept the browser, connection, machine and test procedure under our direct control instead of mixing results from different remote test nodes.
Cold Browser, Warm Page Cache
Before every cold-browser run, Chrome's Clear site data function was used. Cache Storage, IndexedDB, local/session storage, service workers, cookies and third-party cookies were cleared.
Cold browser did not mean deliberately cold server-side page cache. Before a benchmark state was considered valid, the relevant plugin had been allowed to generate the optimized page and any required CSS/preload artifacts. This became particularly important during the WP Rocket tests, where one early run was captured while preload work was still queued and was excluded from the final dataset.
Warm-browser runs were used where they answered a meaningful question, most notably for LiteSpeed Deferred. Interaction was treated as a separate axis only for configurations whose JavaScript execution was actually gated by visitor activity.
Why We Use Multiple Runs
A single Lighthouse result is not enough for a meaningful performance comparison. Browser scheduling, network timing, asynchronous resources, layout shifts and transient server activity can all move the score even when the configuration is unchanged.
For every benchmark state, we performed at least three independent Lighthouse runs and report the median, never the highest score. Some earlier benchmark states were measured five times; those additional runs were retained rather than discarded.
This matters because isolated outliers did occur. The median lets us keep those runs in the evidence without allowing one unusual layout shift or network event to dominate the conclusion.
Before Optimizing Anything: The Baseline
Before testing any caching or performance plugin, we disabled the WordPress performance optimization layer and measured the same production WooCommerce installation without LiteSpeed Cache, WP Rocket or UltraCache active.
Nothing else was changed. LiteSpeed Enterprise remained underneath WordPress, Redis remained available, and the theme, WooCommerce installation, active plugins, third-party integrations and production content were unchanged.
The baseline was not intentionally crippled. We simply wanted to know how fast the site was before a WordPress performance plugin started changing frontend delivery.
Across the original baseline measurements, Lighthouse returned:
85 / 86 / 80 / 86 / 85 -> median 85
| Metric | Baseline |
|---|---|
| Performance | 85 |
| FCP | 0.7 s |
| LCP | 2.1 s |
| TBT | 0 ms |
| CLS | 0.014 |
| Speed Index | 2.1 s |
One result immediately stands out: Total Blocking Time was already 0 ms. This was not an overloaded server or a site suffering from catastrophic JavaScript execution. The main opportunity was rendering and resource delivery: LCP, visual completion, CSS/JavaScript delivery and caching.
The document response itself was typically around 740-760 ms in these baseline tests. That gives us a useful reference point for everything that follows.
The central question is therefore not simply which plugin can print the largest number. It is how each plugin reaches that number, what remains pending behind it, and how much of the advantage survives when a visitor actually interacts with the page.
Part 1 - LiteSpeed Cache
Configuring LiteSpeed Cache for Maximum Performance
We used LiteSpeed Cache 7.9 on LiteSpeed Enterprise 6.3.5 with native LSAPI/LSPHP. Rather than using conservative defaults, we started from the Extreme preset and manually tuned it until the production WooCommerce site was visually correct and functionally stable.
The final configuration retained aggressive page caching, Redis object caching, CSS and JavaScript optimization, UCSS/Critical CSS, lazy loading, responsive placeholders, VPI and WooCommerce ESI.
We did not disable major optimization features simply because they created a compatibility issue. We traced the issue and added the minimum targeted exclusion required.
Compatibility Tuning Required
The Extreme preset was not immediately production-ready on this site. UCSS initially broke product carousels generated by the Salient theme. The problem was traced to the theme's dynamic stylesheet, which had to be excluded from UCSS processing while UCSS itself remained enabled.
Delayed JavaScript also exposed a dependency chain involving the WordPress Consent API and WooCommerce attribution/analytics code. Targeted exclusions were added rather than abandoning JavaScript optimization.
After tuning, the site rendered correctly and produced no runtime JavaScript errors. Reaching that point, however, required considerable manual compatibility debugging.
QUIC.cloud Optimization Services
QUIC.cloud Online Services were connected and available to LiteSpeed Cache for cloud-based optimization features such as UCSS/Critical CSS/VPI. QUIC.cloud CDN itself was not in the request path; the benchmark domain resolved directly to the origin server.
A Guest Mode Problem Discovered During Testing
LiteSpeed's Guest Mode interacted poorly with the fully cold-browser methodology used here. One diagnostic run with Guest Mode enabled scored 79, transferred roughly 16.4 MiB and triggered a Lighthouse incomplete-load warning. After disabling Guest Mode while keeping the remaining aggressive optimizations, a comparable run returned to the mid-90s with roughly 7.1 MiB transferred.
Guest Mode and Guest Optimization were therefore disabled for the final LiteSpeed dataset. Earlier Guest-Mode-influenced results were treated as diagnostic evidence and not used as the final benchmark numbers.
LiteSpeed Deferred JavaScript
We first tested the tuned Extreme configuration with JavaScript set to Deferred rather than Delayed. In this mode, execution does not depend on the visitor moving the mouse, clicking or scrolling.
Cold-browser runs scored:
91 / 96 / 96 -> median 96
Warm-browser runs then scored:
96 / 97 / 97 -> median 97
| State | Performance | FCP | LCP | TBT | CLS | Speed Index |
|---|---|---|---|---|---|---|
| Cold browser | 96 | 0.8 s | 1.2 s | 0 ms | 0.005 | 1.4 s |
| Warm browser | 97 | 0.6 s | 1.1 s | 0 ms | 0.005 | 1.4 s |
The 91-point cold run was driven mainly by an isolated 0.139 CLS event; the other rendering metrics remained close to the surrounding runs. The important point is that LiteSpeed can remain very fast even when JavaScript is not hidden behind an interaction gate.
LiteSpeed Delayed JavaScript
We then switched back to Delayed JavaScript and treated visitor interaction as part of the benchmark. This gives two legitimate views of the same optimized page: the untouched Lighthouse state and the state after mouse movement releases delayed work.
Without interaction:
98 / 98 / 98 -> median 98
With mouse interaction:
94 / 95 / 94 -> median 94
| State | Performance | FCP | LCP | TBT | CLS | Speed Index |
|---|---|---|---|---|---|---|
| No interaction | 98 | 0.6 s | 1.0 s | 0 ms | 0.003 | 1.0 s |
| Mouse interaction | 94 | 0.6 s | 1.2 s | 0 ms | 0.020 | 1.7 s |
What happens when the visitor moves the mouse?
The headline score moved from 98 to 94. FCP remained essentially unchanged and TBT stayed at 0 ms, but LCP, CLS and especially Speed Index worsened once the delayed workload was released.
The DOM also expanded from roughly 1,206-1,207 elements before interaction to about 1,266 after interaction, confirming that the page entered a materially different frontend state.
This is the key distinction with interaction-gated optimization: Lighthouse can measure a lighter state than the one a real visitor reaches a moment later.
Is LiteSpeed "cheating"?
No. Delayed JavaScript is a documented optimization mechanism, and the synthetic no-interaction result is a legitimate Lighthouse result for that configuration. The more useful question is what the number represents.
If the question is "What does Lighthouse score before the visitor interacts?", 98 is the answer. If the question is "How much of that performance survives when delayed frontend work begins?", the mouse-interaction median of 94 is equally relevant.
Keeping both numbers is more informative than pretending only one state exists.
LiteSpeed ultimately delivered excellent performance, but its most aggressive configuration required the most compatibility tuning of the three products tested here.
Part 2 - WP Rocket
WP Rocket Setup: More Manual Configuration, but No Debugging Required
WP Rocket 3.23.2.2 was configured aggressively rather than left at conservative defaults. Remove Unused CSS, CSS/JavaScript minification, JavaScript defer, JavaScript delay, image lazy loading, font optimization, preload and related performance features were used as appropriate.
WP Rocket did require deliberate setup. The operator still has to understand which optimization switches to enable and how those features interact.
But there was a major practical difference from LiteSpeed: the first aggressive WP Rocket configuration worked immediately.
The CSS rendered correctly, the WooCommerce frontend remained functional, and the first runtime check showed zero JavaScript console errors. No JavaScript dependency tracing, no broken-carousel debugging and no hand-built exclusion list were required.
That deserves credit. On this site, WP Rocket required configuration, but not compatibility debugging.
RocketCDN Was Used for Static Asset Delivery
RocketCDN was active during the WP Rocket benchmark and served static assets, fonts, JavaScript and media. This is intentionally disclosed because it differs from LiteSpeed, where QUIC.cloud Online Services were available but QUIC.cloud CDN was not in the request path.
We kept RocketCDN enabled because it was legitimately available in the WP Rocket setup used for this benchmark. The result therefore reflects the strongest practical WP Rocket configuration available to us, not an artificially restricted one.
The site also retained its large hero WebM, so the benchmark was not improved by removing the real production media workload.
WP Rocket with JavaScript Defer
We first measured WP Rocket with JavaScript defer as the primary execution strategy. Mouse movement was tested separately and produced no meaningful repeatable difference, which is consistent with defer not being interaction-gated.
Five runs were retained:
93 / 93 / 95 / 94 / 94 -> median 94
| Metric | WP Rocket Defer |
|---|---|
| Performance | 94 |
| FCP | 0.8 s |
| LCP | 1.5 s |
| TBT | 0 ms |
| CLS | 0.019 |
| Speed Index | 1.4 s |
WP Rocket was therefore already fast before adding an interaction gate.
WP Rocket with Defer + Delay
For the second profile, both Load JavaScript Deferred and Delay JavaScript Execution were enabled. Delay Safe Mode remained off and no JavaScript exclusions were added. Again, the site produced no runtime JavaScript errors.
No interaction:
96 / 95 / 96 / 97 / 96 -> median 96
Mouse interaction:
94 / 96 / 96 / 95 / 94 -> median 95
| State | Performance | FCP | LCP | TBT | CLS | Speed Index |
|---|---|---|---|---|---|---|
| No interaction | 96 | 0.9 s | 1.2 s | 0 ms | 0.009 | 1.1 s |
| Mouse interaction | 95 | 1.0 s | 1.2 s | 0 ms | 0.020 | 1.5 s |
The delay was effectively indefinite until interaction
In our test, WP Rocket Delay behaved as an indefinite interaction gate during the audit: if no interaction occurred, the delayed JavaScript did not automatically begin executing within a short fallback window.
That matters visually. In the untouched state, some dynamically initialized elements were not yet visible because the JavaScript responsible for creating or initializing them had not run.
Once the mouse moved, the delayed workload was released. The DOM increased from roughly 1,282 elements to around 1,341, and theme initialization, jQuery, WooCommerce and other frontend scripts became active. Forced reflows also appeared in the interaction traces.
Despite that aggressive behavior, the score only moved from 96 to 95, and the browser console still showed no JavaScript runtime errors. WP Rocket therefore handled a very aggressive delay strategy on this production site without requiring a single manual JavaScript exclusion.
A preload-state diagnostic that we excluded
Immediately after changing File Optimization settings, one Lighthouse run scored about 80. We did not accept it as a benchmark result because WP Rocket was still rebuilding its optimized state in the background.
Database and Action Scheduler inspection showed Remove Unused CSS work completed, but dozens of preload URLs were still pending or in progress. After the homepage itself reached completed status, the repeated tests stabilized in the 95-97 range.
This reinforced an important benchmark rule: cold browser, warm server/page cache.
Operational control: preload was less directly observable
WP Rocket preload eventually completed correctly, but the process was comparatively asynchronous and less directly observable. After changing optimization settings, determining whether the page was genuinely ready sometimes required checking background queues rather than simply watching a deterministic warm-up process finish.
For normal production traffic this may be a minor operational detail. For benchmarking, deployment and troubleshooting, however, direct warm-up control and progress visibility make reproducibility easier.
Uninstall was not completely clean
One negative point appeared only after the WP Rocket benchmark was finished.
In our test, uninstalling WP Rocket did not leave the WordPress installation completely clean. Cache-related artifacts remained behind, including the wp-content/advanced-cache.php drop-in.
That file matters because advanced-cache.php is loaded very early in the WordPress bootstrap when caching is enabled. A stale drop-in from a previous caching plugin can therefore continue affecting the site after the plugin itself has been removed and can interfere with the next caching solution.
In our case, the leftover drop-in caused a real compatibility problem and had to be removed manually. Before the UltraCache benchmark began, we explicitly cleaned that artifact so the next plugin would not inherit WP Rocket state.
This does not change WP Rocket's Lighthouse results, but it does affect the overall operational experience. A cache plugin should ideally remove runtime components that can continue influencing WordPress after uninstall.
WP Rocket did not reach the highest synthetic score in this comparison, but it produced a strong result with notably little compatibility effort. Its main operational weaknesses in this test were less direct preload observability and an uninstall that left a cache drop-in behind.
Part 3 - UltraCache
Installing UltraCache After the Other Benchmarks
After the LiteSpeed and WP Rocket tests were complete, UltraCache was installed on the same WooCommerce website. Before doing so, the leftover WP Rocket cache drop-in was manually removed so the UltraCache results could not be contaminated by another plugin's runtime artifact.
The server, WordPress installation, theme, plugins, content, third-party integrations, Lighthouse environment and browser reset procedure remained the same.
The setup process was different: instead of manually selecting and tuning a long list of optimization switches, we used the One-Click Optimization Wizard.
Optimize UltraCache for User Experience
The first profile was Optimize UltraCache for User Experience. The intent of this mode is to optimize the initial load aggressively without making important functionality wait indefinitely for visitor interaction.
Compatibility-sensitive JavaScript can remain available through normal or deferred execution, while selected non-critical work is postponed. For delayed local JavaScript in this profile, there was a two-second fallback: interaction could release it sooner, but doing nothing would not leave it dormant forever.
That distinction matters on ecommerce pages, where navigation, sliders, product controls and other JavaScript-driven elements should become usable naturally rather than waiting for a synthetic trigger.
We moved the mouse in every User Experience run
For these runs we deliberately generated mouse interaction so the benchmark did not reward a perfectly dormant page. Browser site data was cleared before every run, and five independent Lighthouse runs were retained.
97 / 97 / 97 / 97 / 97 -> median 97
| Metric | UltraCache - User Experience |
|---|---|
| Performance | 97 |
| FCP | ~0.7 s |
| LCP | ~1.0 s |
| TBT | 0 ms |
| CLS | ~0.012 |
| Speed Index | ~1.4 s |
All five runs returned exactly 97. More importantly, the result was achieved while the page was already being pushed into an active visitor state.
The value of this profile is therefore not just its score. It represents an optimization strategy that prioritizes automatic functional availability rather than maximizing the amount of code hidden from Lighthouse.
Optimize UltraCache for Speed
We then reran the Wizard using Optimize UltraCache for Speed. This is the aggressive benchmark-oriented profile: substantially more JavaScript remains outside the initial execution path until visitor interaction occurs.
Like the other interaction-gated modes in this article, the no-interaction score should therefore be read as a synthetic state, not as proof that every JavaScript-dependent interface has already initialized.
Without interaction:
99 / 99 / 99 / 99 / 99 -> median 99
With mouse interaction:
98 / 93 / 98 / 98 / 98 -> median 98
| State | Performance | FCP | LCP | TBT | CLS | Speed Index |
|---|---|---|---|---|---|---|
| No interaction | 99 | 0.8 s | 0.9 s | 0 ms | 0.009 | 0.8 s |
| Mouse interaction | 98 | 0.7 s | 1.0 s | 0 ms | 0.014 | 1.0 s |
The 93-point interaction run was retained. It was driven by a large layout shift from the site's consent interface rather than CPU blocking; the median remained 98.
The headline transition was therefore 99 -> 98. LCP moved from 0.9 to 1.0 seconds, Speed Index from 0.8 to 1.0 seconds, and TBT remained at 0 ms.
Warm-up control and observability
A practical difference became clearer after the WP Rocket preload investigation. UltraCache warm-up could be started immediately, its progress observed directly, and the operator could see when the requested warm process had finished.
That does not make a Lighthouse score higher by itself, but it reduces ambiguity when deploying, troubleshooting or reproducing a benchmark state.
UltraCache delivered the highest synthetic score in this dataset and retained almost all of it after interaction. Its User Experience profile also provided a separate production-oriented option that avoided indefinite local JavaScript dormancy while still scoring 97.
Conclusion: Benchmark Score vs. Visitor Performance
With three caching plugins in the comparison, the result is more interesting than a simple winner/loser table.
All three products were capable of producing excellent Lighthouse scores on the same heavy WooCommerce site. The meaningful differences appeared in how much work was postponed, how the page changed after interaction, and how much operator effort was required to reach and maintain the optimized state.
Total Blocking Time was 0 ms in every final benchmark state, so the comparison below focuses on the metrics that actually separated the configurations.
| Plugin / profile | State | Median | FCP | LCP | CLS | Speed Index |
|---|---|---|---|---|---|---|
| Baseline | No performance plugin | 85 | 0.7 s | 2.1 s | 0.014 | 2.1 s |
| LiteSpeed Deferred | Cold browser | 96 | 0.8 s | 1.2 s | 0.005 | 1.4 s |
| LiteSpeed Deferred | Warm browser | 97 | 0.6 s | 1.1 s | 0.005 | 1.4 s |
| LiteSpeed Delayed | No interaction | 98 | 0.6 s | 1.0 s | 0.003 | 1.0 s |
| LiteSpeed Delayed | Mouse interaction | 94 | 0.6 s | 1.2 s | 0.020 | 1.7 s |
| WP Rocket Defer | Cold browser | 94 | 0.8 s | 1.5 s | 0.019 | 1.4 s |
| WP Rocket Defer + Delay | No interaction | 96 | 0.9 s | 1.2 s | 0.009 | 1.1 s |
| WP Rocket Defer + Delay | Mouse interaction | 95 | 1.0 s | 1.2 s | 0.020 | 1.5 s |
| UltraCache - User Experience | Mouse interaction | 97 | ~0.7 s | ~1.0 s | ~0.012 | ~1.4 s |
| UltraCache - Speed | No interaction | 99 | 0.8 s | 0.9 s | 0.009 | 0.8 s |
| UltraCache - Speed | Mouse interaction | 98 | 0.7 s | 1.0 s | 0.014 | 1.0 s |
What the interaction tests changed
The interaction-gated profiles tell three different stories:
- LiteSpeed Delayed: 98 -> 94
- WP Rocket Defer + Delay: 96 -> 95
- UltraCache Speed: 99 -> 98
None of those no-interaction scores is invalid. They simply describe a lighter execution state in which some delayed work has not yet run. The mouse-interaction result answers the complementary question: how much measured performance remains after the page begins behaving more like the state a real visitor creates.
Setup and operational experience also mattered
| Plugin | Observed setup / operations in this test |
|---|---|
| LiteSpeed Cache | Highest compatibility-debugging burden. Extreme required targeted JS and UCSS exclusions. Final site was stable. |
| WP Rocket | Manual configuration required, but the first aggressive setup worked without JS/CSS debugging. Preload was more asynchronous to observe. Uninstall left advanced-cache.php behind in our test. |
| UltraCache | One-Click Wizard produced both tested profiles. Warm-up could be started and observed directly to completion. |
These are not Lighthouse metrics, but they are part of the real cost of running a cache plugin in production.
A note on CDN fairness
The network path was not identical for every product. WP Rocket used RocketCDN because it was available in the tested WP Rocket setup. LiteSpeed had QUIC.cloud optimization services available but not QUIC.cloud CDN in the request path. UltraCache used the same origin infrastructure without adding a separate benchmark CDN layer.
We chose transparency over artificially disabling a legitimate product capability. Readers should therefore interpret the results as best practical production configurations, not as a controlled CDN-vs-CDN laboratory experiment.
The benchmark in one sentence
LiteSpeed Cache, WP Rocket and UltraCache all produced strong synthetic performance, but the interaction tests exposed how much work each delayed strategy was postponing; UltraCache achieved the highest score and retained the most measured performance after interaction, WP Rocket was exceptionally smooth from a compatibility perspective but less clean operationally at preload/uninstall, and LiteSpeed delivered excellent numbers after the greatest amount of manual tuning.
The most important conclusion is therefore not which plugin can generate the highest isolated Lighthouse number. It is how much real functionality and real visitor workload can be introduced before that number changes - and how much work the operator must do to get there and keep the site in a known-good state.