UltraCache

WordPress performance plugin

UltraCache

Make WordPress pages load faster, reduce server work, optimize images and frontend files, and keep every cache layer ready for visitors.

Version 2.59.12.44WordPress 6.9 or newerPHP 8.1 or newerGPL-2.0-or-later

Features

Everything needed to make WordPress faster

UltraCache combines the main performance jobs in one place, so the site loads faster and cached content stays current.

Faster page delivery

Serve prepared HTML to visitors instead of rebuilding the same public page on every request. UltraCache also clears and rebuilds affected pages automatically after content changes.

Faster WordPress and database work

Use Redis, APCu, SQLite, runtime memory, or disk object cache to reuse database results and WordPress objects across public pages, dynamic requests, and the admin area.

Smaller, modern images

Create AVIF and WebP versions of Media Library images, choose the preferred format and fallback, process new uploads automatically, and convert existing images in the background.

Media Library Replacement

Replace original Media Library files and registered sizes with verified optimized versions while updating WordPress metadata, database references, and active theme CSS references.

Lighter CSS and local fonts

Reduce render-blocking work with CSS bundles and asynchronous delivery, keep Google Fonts local, optimize self-hosted font CSS, and delay icon fonts until they are needed.

JavaScript optimization and Error Handler

Defer or delay non-critical scripts to improve the first load. When a browser error appears, paste it into the JavaScript Error Handler to generate targeted safeguard rules instead of disabling optimization.

Faster first screen and steadier layouts

Give the most important image, SVG, video poster, or text element priority, lazy-load later images and eligible iframes, and add dimensions that reduce layout movement.

Automatic cache warm-up

Prepare the homepage, menu pages, selected URLs, or the full site before visitors arrive. Content updates can warm only the pages that were actually affected.

Varnish and ESI

Keep Varnish synchronized with WordPress through HTTP PURGE or Admin BAN, refill updated pages, use soft purge and stale refresh when supported, and deliver public or private ESI fragments, including the classic WooCommerce mini-cart.

LiteSpeed integration

Work with LiteSpeed page cache, clear and refill the correct HTML variants, refresh stale pages, and keep the WordPress and server cache layers synchronized.

WP-CLI and background processing

Run cache, warm-up, media, object-cache, and Varnish jobs from the command line while resumable queues handle larger jobs without tying them to one browser request.

Performance diagnostics

Find what is slowing down your website across page delivery, object cache, images, CSS, JavaScript, warm-up jobs, and server cache integrations. UltraCache brings the relevant results together so you can focus on the actual bottleneck.

Installation

Recommended setup

Start with the recommended settings, prepare the first cache and image set, then check the public site in a private browser window.

Initial configuration

Configure UltraCache

  1. Activate the Aggressive profile. It enables the main performance options, Warm affected pages after save, and Apache Static HTML Delivery.
  2. Check HTML Compression. Open the dropdown under HTML Compression in Cache Engine and run the check so UltraCache can use the server result.
  3. Select the main menu for warm-up. Choose the primary frontend menu and the required depth. First-level menu URLs suit most websites.
  4. Choose Full-site warm-up sources. Homepage / blog index, Selected menu URLs, Pages, Posts, and Categories suit most sites.
  5. Enable Convert new uploads. New Media Library uploads will use the selected image conversion policy automatically.
  6. Set Maximum upload image side. 1920 pixels is appropriate for most modern websites.
  7. Choose the image formats. AVIF provides strong compression, WebP provides broad compatibility, and AVIF with WebP fallback is a strong general-purpose configuration.
  8. Choose Image compression level. Compact provides strong size reduction with little visible difference for normal website images.
  9. Test AVIF before the first batch. Run Image conversion test and then Check test.
  10. Enable the main font optimizations. Local Google Fonts Optimization, Bundle Generated Font-Mix CSS, and Delay icon fonts.
  11. For WooCommerce, enable Suppress empty-cart execution.
  12. For MailerLite, enable Lazy MailerLite nonce refresh. The option is in Advanced Settings.
  13. Confirm the detected Object Cache backend. APCu is fast local cache, Redis is persistent, and SQLite is available when neither is present.
  14. Configure Varnish when present. Enter the required connection and purge details in the Varnish Cache box.
  15. Enable scheduled warm-up. In Automation and Scheduling, turn on Warm full site after Scheduled Cleanup.
Prepare after saving

Build the first cache and media set

  1. Run Flush All Cache to clear previous cached output.
  2. Run Warm Up Menu HTML Cache + Separate CSS Bundles to prepare the main pages immediately.
  3. Run Start / Resume Conversion in AVIF / WebP Batch Conversion to prepare existing Media Library images.
  4. Use Full-site warm-up when the complete selected URL set should be cached.
Must-do post-install JavaScript check

Verify the public site

Run this check after the first setup and after major JavaScript optimization changes. Use a private browser window so you test the public cached page rather than a logged-in administration session.

  1. Open the website in a private window. Use Ctrl+Shift+N in Chrome or Edge, or Ctrl+Shift+P in Firefox.
  2. Open the browser Console. Press F12, select Console, and reload the page.
  3. Check the visible page functions. Open the menu and use the main slider, form, popup, search, cart, or other interactive elements present on that page.
  4. Copy any JavaScript errors. If no red JavaScript errors appear, the post-install check is complete. Otherwise copy the full error lines and their stack traces.
  5. Open the JavaScript safeguards section. In the UltraCache dashboard, expand JS Defer / Delay Safeguards & Diagnostics.
  6. Analyze the copied errors. Paste them into Console Error Handler and click Extract Console Error Suggestions.
  7. Append the proposed fixes. Use Append to Defer Instead for the normal compatibility fix. Use Append to Do Not Defer or Delay for suggestions placed in that fallback group or when the same error remains after the first pass.
  8. Save the safeguard lists. Click Save Both Lists after appending the required suggestions.
  9. Flush and warm the cache again. Run Flush All Cache, then warm the front page. Front-page warm-up is enough during this testing loop.
  10. Repeat until the Console is clear. Reload the anonymous page and repeat the same process until no JavaScript errors remain.
Performance and PageSpeed

Improve scores methodically

  1. Review the largest CSS bundle sources. Open CSS Bundle Exclusions and Diagnostics, then click Run CSS Diagnostics. Under Top CSS bundle sources by bytes, you will see which CSS files contribute the most to the generated bundle. Excluding one or two of the largest files, especially large theme stylesheets, can often provide a significant performance improvement. Add exclusions one at a time and run another performance test after each change, as the best configuration depends on the theme and page structure.
  2. Enable Delay non-critical/local JS. This can provide a significant PageSpeed and Lighthouse boost, but it can break JavaScript without visible errors, making problems difficult to find and fix.
  3. Cache query-string URLs. Open Query-string args caching and enable it. Under Query-string args whitelist, click Populate, then click Save Query-string Whitelist. UltraCache can then cache eligible query URLs such as /YourProductURL?color=red.
  4. Do not enable options blindly. The Aggressive profile usually provides the best starting point for higher performance scores. Some options are intended only for specific themes, plugins, or compatibility cases. Enabling options that your website does not need may reduce performance or cause visual or functional problems.

Help

FAQ

Page Cache & Delivery10 questions
Is the WordPress admin area cached?

UltraCache does not page-cache WordPress administration pages under /wp-admin/. When Object Cache is enabled, WordPress admin requests still benefit from cached database results, options, and reusable WordPress objects. This can significantly improve dashboard, editor, and plugin-management performance while every admin page remains dynamic.

Are logged-in users cached?

Logged-in users bypass the public page cache by default. They can still benefit from Object Cache on the frontend and inside the WordPress admin area.

Are WooCommerce cart, checkout, and account pages cached?

No. Dynamic WooCommerce pages such as Cart, Checkout, and My Account are excluded from shared public page caching.

Does UltraCache cache URLs with query strings?

Only when every query key is explicitly permitted by the configured query-string allowlist. When the allowlist is empty, query-string requests bypass page cache.

Can UltraCache be used with another page-cache plugin?

Two page-cache systems should not manage the same site at the same time. They may compete for rewrite rules, cache files, and the WordPress advanced-cache.php drop-in. Disable the other page-cache layer before enabling UltraCache page caching.

What does Apache Static HTML Delivery do?

On compatible Apache configurations, it lets the web server deliver eligible cached HTML directly through .htaccess without loading WordPress or PHP for each cached request.

Does UltraCache compress HTML?

UltraCache can handle HTML compression when the server is not already doing it. Use the HTML Compression check under Cache Engine to detect whether compression is already provided by Apache, Nginx, LiteSpeed, a CDN, or another server layer.

What does Flush All Cache remove?

It clears the UltraCache page cache, flushes the active UltraCache Object Cache, invalidates rebuildable frontend cache data, and can also purge selected external/server cache layers when those options are enabled. It does not delete WordPress content, original Media Library files, generated AVIF/WebP images, or the local Google Fonts cache.

Should I flush the cache after editing a post or page?

Normally no. When Warm affected pages after save is enabled, UltraCache clears and warms the related URLs automatically. Use Flush All Cache after broader changes such as theme updates, global CSS or JavaScript changes, plugin changes that alter frontend output, or major optimization-setting changes.

Why can the first uncached visit be slower?

The first eligible request after a purge may need to generate the page HTML and related frontend cache data. Warm-up prepares selected URLs before normal visitors reach them.

Warm-up & Automation9 questions
What is cache warm-up?

Cache warm-up visits selected public URLs and creates their cache before a normal visitor opens them.

Which menu warm-up depth should I use?

The first menu level suits most websites because it normally contains the most important pages without creating an unnecessarily large queue. Greater depth can add hundreds or thousands of URLs.

Which full-site warm-up sources should I select?

Homepage / blog index, Selected menu URLs, Pages, Posts, and Categories cover most websites. Add other post types, archives, or taxonomies only when those public URLs are useful to visitors.

Does full-site warm-up process every URL immediately?

No. URLs are added to a controlled queue and processed according to the warm-up settings and available server resources.

What does Warm affected pages after save do?

When content changes, UltraCache builds one canonical affected-URL plan, purges its old HTML and CSS cache, and queues the cacheable pages for HTML, configured CSS bundle, and optional Varnish rebuild without warming the entire site.

How does background full-site warm-up start?

Enable Warm full site after Flush All Cache and/or Warm full site after Scheduled Cleanup. Each trigger builds a background plan from the selected Full-site warm-up sources and applies the Scheduled / Cron warm limit.

How do I run a full-site warm-up from WP-CLI?

This command uses UltraCache's existing full-site URL discovery and foreground warm-up pipeline. It warms the original, WebP, and AVIF HTML buckets, builds Separate CSS Bundles, and runs verified Varnish or LiteSpeed stages for the same URLs. Dynamic cart, checkout, account, and other non-cacheable pages are skipped normally.

Replace the three example paths with the PHP executable, WP-CLI file, and WordPress installation paths on your server:

/full/path/to/php \
    -d memory_limit=2048M \
    -d max_execution_time=0 \
    /full/path/to/wp/wp \
    --path=/full/path/to/wordpress \
    ultracache warm_html_all_css \
    --buckets=orig,webp,avif

WP-CLI runs as a foreground warm-up owner. A newer UI or WP-CLI warm-up takes ownership, while background cron work yields automatically.

Does cache warm-up also convert images?

No. Page warm-up and image conversion are separate operations. Use AVIF / WebP Batch Conversion to prepare existing Media Library images.

Can a very large warm-up selection take a long time?

Yes. Deep menus, many custom post types, and large archive or taxonomy selections can create a substantial queue. Select the URL sources that visitors actually use.

CSS, JavaScript & Fonts8 questions
What is the difference between Defer and Delay JavaScript?

Defer downloads a script during page loading but executes it after the HTML has been parsed. Delay postpones execution until the configured trigger, such as interaction or timing.

What are Defer parallel execution and Delay parallel execution?

They control parallel execution separately for the Defer and Delay script groups. They are not first-party and third-party switches.

What should I do if a menu, slider, form, or popup stops working?

Identify the affected script and add the relevant handle or URL pattern to the appropriate exclusion or compatibility list. There is normally no need to disable all JavaScript optimization.

Does UltraCache combine every stylesheet into one global file?

No. UltraCache can build optimized CSS bundles and keep page-specific CSS separate where appropriate, so one page does not need to load CSS that belongs only to another page.

When should I rebuild Separate CSS Bundles?

Rebuild them after changes to global styling, theme output, page-builder CSS, or CSS optimization settings. A normal text edit does not usually require a complete rebuild.

What does Local Google Fonts Optimization do?

It downloads supported Google Fonts from the site configuration to the WordPress server and serves local copies instead of requiring visitor browsers to retrieve them from Google.

What does Bundle Generated Font-Mix CSS do?

It combines generated local-font declarations and related font CSS into an optimized local resource.

What does Delay icon fonts do?

It postpones icon-font styles that are not required for the first visible render, including supported Font Awesome, Elementor, Material Icons, Swiper, and theme-specific icon fonts.

LCP Optimization13 questions
What is LCP?

Largest Contentful Paint is the largest visible content element rendered during the initial page load. It can be an image, heading, text block, video poster, CSS background, or slider background.

Does UltraCache assume that the LCP element is always an image?

No. UltraCache can learn text, images, video first frames, posters, and background images. Confirmed video LCP elements receive direct priority markup, while image and poster mappings can also emit image preloads.

How does automatic LCP detection work?

When LCP Frontend Discovery is enabled and no manual selector is configured, UltraCache observes the actual browser LCP on eligible cacheable pages without query parameters. The first result is used immediately, and the mapping locks when the same candidate appears in two of the last three visits.

Why does automatic LCP detection require more than one observation?

The first observation is used immediately. A two-of-three rolling confirmation then locks the result and stops discovery for that page and viewport, reducing the chance that a temporary slider or timing variation becomes permanent.

Are LCP mappings stored separately by viewport?

Yes. A page can have different confirmed LCP mappings for different viewport classes, such as a heading on a smaller screen and a background image on a larger screen.

What happens when I configure a manual LCP selector?

Manual selectors take precedence over automatic LCP learning.

Does LCP learning require Lighthouse?

No. LCP Frontend Discovery learns from normal eligible visits while it is enabled. Lighthouse or PageSpeed can be used afterward to measure the result.

What happens when the confirmed LCP is text?

UltraCache records the text element and does not add an unrelated image preload for that mapping.

What is shown in LCP Diagnostics & Settings?

LCP Diagnostics & Settings loads ten discovered URLs only after the accordion opens. Full viewport, selector, resource, confirmation, and refresh details are requested only after you select a URL.

What does Relearn do?

Relearn keeps the current mapping active as a fallback, clears its confirmation evidence, and allows new eligible visits to learn and lock a replacement for the same viewport.

What does Forget mapping do?

It removes the stored mapping and refreshes the page cache without it. The next eligible visit can start learning a replacement while LCP Frontend Discovery is active.

Why is an LCP refresh pending?

The mapping has been confirmed, but the affected page is still waiting for its page cache to be rebuilt by the warm queue.

Do logged-in administrator visits create automatic LCP observations?

When administrator-only discovery is enabled, only logged-in administrators contribute. Otherwise anonymous public visits and full administrators can contribute while the configured discovery period is active.

Images & Media Library16 questions
What is the difference between AVIF and WebP?

AVIF usually produces smaller files. WebP provides broader compatibility with older software, image tools, and some hosting environments.

Can AVIF be used with a WebP fallback?

Yes. A common configuration is AVIF as the primary format and WebP as the fallback.

Should I test AVIF before using it?

Yes. Run Image conversion test and then Check test. This verifies the server encoder and lets you compare the generated results, including transparency when suitable PNG files are available.

What image compression level should I use?

Compact suits most normal website images and usually provides a strong file-size reduction with little visible difference. Photography, artwork, or detailed product imagery may need a higher-quality setting.

What does Maximum upload image side control?

It limits the largest width or height of newly uploaded raster images. A value of 1920 suits most websites; increase it when the site genuinely needs larger source images.

Are SVG files converted to AVIF or WebP?

No. SVG is a vector format and remains SVG.

What does Convert new uploads do?

It converts newly uploaded raster images to the selected Upload image format, applies the Maximum upload image side limit, and uses the shared Image compression level.

Does changing image quality rebuild existing optimized files?

Not by itself. Enable Regen. existing and run the conversion process when existing AVIF or WebP files should be recreated with the current quality.

What does Start / Resume Conversion do?

It processes existing Media Library images through the AVIF/WebP batch queue and continues an interrupted conversion from its saved progress.

What does Rebuild / Repair Media Queue do?

It reconstructs the media-processing queue from the current Media Library and output policy. It is used when queue state is missing or inconsistent.

What does Recount Optimized Image Files do?

It recalculates the dashboard counts for existing optimized image files. It does not create new images.

What does Clear Completed Queue Rows do?

It removes completed records from the media queue. It does not delete the generated AVIF/WebP files.

What is the difference between Image Optimization and Media Library Replacement?

Image Optimization creates alternative AVIF/WebP files while retaining the normal Media Library structure. Media Library Replacement is a separate advanced workflow that can promote verified converted files into attachment metadata, generated sizes, database references, and supported active-theme CSS references.

Does Media Library Replacement delete originals immediately?

No. The workflow separates Check, Prepare, Do, Verify, and Delete Originals. Original cleanup remains unavailable until the replacement files and supported references have been verified.

Can Media Library Replacement continue after an interrupted request?

Yes. Its long-running stages persist progress and can pause, resume, or retry.

I have SSH access, but no root access or WP-CLI. How can I run the image conversion?

You can download and run WP-CLI inside your own hosting account. Root access is not required.

A. Download WP-CLI

It is usually best to keep the WP-CLI executable outside the WordPress installation directory.

cd ~

mkdir -p wp
cd wp

wget -q \
    https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar \
    -O wp

chmod 755 wp

Run the following command and note the returned directory:

pwd

Your WP-CLI executable will be located at:

/full/path/returned/by/pwd/wp
B. Find the correct PHP executable

Run:

find / \
    -type f \
    -name "php" \
    -path "*/bin/*" \
    -print \
    2>/dev/null

The server may return several PHP executables. Select the same PHP version that your WordPress website uses. You can find the website’s current PHP version in UltraCache → Advanced Diagnostics → PHP Version.

C. Find the WordPress installation path

Go to the directory containing wp-config.php and run:

pwd

Note the full path returned by the command.

D. Run the image conversion

Replace the example paths below with the PHP, WP-CLI, and WordPress paths you found above:

/full/path/to/php \
    -d memory_limit=2048M \
    -d max_execution_time=0 \
    /full/path/to/wp/wp \
    --path=/full/path/to/wordpress \
    ultracache media process \
    --media-format=best \
    --batch-size=100 \
    --time-budget=300

The command processes the media queue using the website’s configured UltraCache image format and quality settings.

Object Cache & Drop-ins8 questions
What is the difference between Page Cache and Object Cache?

Page Cache stores completed HTML for public pages. Object Cache stores reusable WordPress data such as query results, options, and calculated objects. Object Cache can improve both frontend and wp-admin requests.

Which Object Cache backend should I use?

Use the backend that is correctly available on the server. APCu is very fast local shared memory, Redis is persistent and can be shared between processes or servers, and SQLite is a disk-based alternative when APCu or Redis is unavailable. Disk is intended for advanced use when another backend is not available.

Is APCu always better than Redis?

APCu is often faster on a single PHP server because it uses local shared memory, but its data does not survive PHP or server restarts. Redis is persistent and can support multi-process or multi-server deployments.

Is SQLite Object Cache suitable for every website?

SQLite is useful when Redis or APCu is unavailable, but its performance depends on storage speed and server concurrency.

Why does UltraCache create advanced-cache.php?

WordPress loads the advanced-cache.php drop-in early so UltraCache can serve eligible page-cache responses before normal WordPress page generation.

Why does UltraCache create object-cache.php?

WordPress uses the object-cache.php drop-in to replace the default runtime object cache with the selected persistent or advanced UltraCache backend.

What happens if another plugin leaves a conflicting cache drop-in?

UltraCache detects conflicting advanced-cache.php and object-cache.php files. When an administrator explicitly chooses Remove, UltraCache deletes the selected conflicting drop-in without creating a backup.

Does Flush All Cache also flush Object Cache?

Yes. Flush All Cache clears the active UltraCache Object Cache as part of the full purge.

WooCommerce & Integrations10 questions
What does Suppress empty-cart execution do?

It reduces unnecessary WooCommerce cart processing when the visitor has no cart contents.

Will UltraCache cache customer-specific WooCommerce data?

No. Customer-specific cart, checkout, account, and other excluded dynamic requests do not use the shared public page cache.

What does Lazy MailerLite nonce refresh do?

It postpones MailerLite nonce refresh work so it does not unnecessarily affect the initial cached page response.

Does UltraCache work with TranslatePress?

Yes. UltraCache can vary cached pages by the active TranslatePress language so translated URLs do not share the wrong HTML cache.

Should I use BAN or HTTP PURGE for Varnish?

Think of PURGE as removing one exact box from a shelf. BAN adds a rule that marks every matching box as unusable. Both prevent visitors from receiving old cached content, but BAN can describe a much larger group in one operation.

Best choice when available: Admin / BAN. Use it when your host provides a working Varnish admin endpoint and secret. UltraCache can verify one URL with Exact BAN, combine many URLs with Batch BAN, clear all HTML for the site, or clear the entire host. It is the most capable option.

Use HTTP PURGE when Admin / BAN is not available. Many managed hosts expose only a local HTTP purge endpoint. UltraCache can still invalidate and refill exact URLs correctly, but site-wide clearing may need known-URL purges plus TTL expiry unless the host exposes additional verified HTTP capabilities.

Choosing Admin / BAN does not mean exact invalidation is missing. Exact BAN performs that job in Admin mode, so Exact PURGE is shown as “Unavailable in Admin/BAN mode.” That label describes the selected control method, not a lost feature. Choose the mode your server actually exposes, then use Test Varnish to see which capabilities are Supported.

Can UltraCache purge Varnish?

Yes. Configure and test the Varnish connection and purge details in the Varnish Cache section.

Can Varnish and UltraCache Page Cache be used together?

Yes. UltraCache can manage its WordPress page cache while Varnish acts as an additional delivery layer, provided the Varnish purge integration is configured so both layers are invalidated together.

My Varnish server has only a basic setup. How can I enable ESI and WooCommerce mini-cart support?

Public ESI requires Varnish to advertise ESI/1.0 and process only HTML responses that explicitly request it. Private/session ESI additionally uses req_top to carry only the built-in allowlisted cookies into signed UltraCache no-store fragment subrequests.

Suggested request-opt-in configuration: The recommended snippet requires two independent signals: the request-side ultracache_esi_optin=1 browser marker and the X-UltraCache-ESI-Shared-Parent: 1 response approval. UltraCache sets the session marker only on pages that render the verified classic mini-cart ESI adapter. Without both signals, WooCommerce requests remain PASS and normal cart behavior is preserved.

This is a suggestion and is not installed automatically. Merge the relevant rules into your existing VCL instead of replacing an unrelated full configuration blindly. Compile/reload Varnish and run Test Varnish again. Frontend ESI composition probes use an independent 20-second timeout; the Admin endpoint timeout controls only Varnish admin socket operations.

sub vcl_recv {
    if (req.esi_level == 0) {
        # Reject spoofed handshake/private-transport headers.
        unset req.http.X-ESI-Private-Request;
        unset req.http.X-ESI-Request-Level;
        unset req.http.X-ESI-Original-Cookie;
        unset req.http.X-UltraCache-ESI-Candidate;
        unset req.http.X-UltraCache-ESI-Cookie-Check;
        unset req.http.X-UltraCache-ESI-Opt-In;
        unset req.http.X-UltraCache-ESI-Shared-Parent;

        if (req.http.Cookie ~ "(?i)(^|;[ ]*)ultracache_esi_optin=1(?:;|$)") {
            set req.http.X-UltraCache-ESI-Opt-In = "1";
        }

        # Copy only the built-in private transport allowlist.
        if (req.http.Cookie ~ "(?i)(^|;[ ]*)esi_session=") {
            set req.http.X-ESI-Original-Cookie = regsub(req.http.Cookie, "(?i)^.*?(?:^|;[ ]*)(esi_session=[^;]*).*$", "\1");
        }
        if (req.http.Cookie ~ "(?i)(^|;[ ]*)woocommerce_items_in_cart=") {
            if (req.http.X-ESI-Original-Cookie) {
                set req.http.X-ESI-Original-Cookie = req.http.X-ESI-Original-Cookie + "; " + regsub(req.http.Cookie, "(?i)^.*?(?:^|;[ ]*)(woocommerce_items_in_cart=[^;]*).*$", "\1");
            } else {
                set req.http.X-ESI-Original-Cookie = regsub(req.http.Cookie, "(?i)^.*?(?:^|;[ ]*)(woocommerce_items_in_cart=[^;]*).*$", "\1");
            }
        }
        if (req.http.Cookie ~ "(?i)(^|;[ ]*)woocommerce_cart_hash=") {
            if (req.http.X-ESI-Original-Cookie) {
                set req.http.X-ESI-Original-Cookie = req.http.X-ESI-Original-Cookie + "; " + regsub(req.http.Cookie, "(?i)^.*?(?:^|;[ ]*)(woocommerce_cart_hash=[^;]*).*$", "\1");
            } else {
                set req.http.X-ESI-Original-Cookie = regsub(req.http.Cookie, "(?i)^.*?(?:^|;[ ]*)(woocommerce_cart_hash=[^;]*).*$", "\1");
            }
        }
        if (req.http.Cookie ~ "(?i)(^|;[ ]*)wp_woocommerce_session_[^=; ]+=") {
            if (req.http.X-ESI-Original-Cookie) {
                set req.http.X-ESI-Original-Cookie = req.http.X-ESI-Original-Cookie + "; " + regsub(req.http.Cookie, "(?i)^.*?(?:^|;[ ]*)((?:wp_woocommerce_session_[^=; ]+)=[^;]*).*$", "\1");
            } else {
                set req.http.X-ESI-Original-Cookie = regsub(req.http.Cookie, "(?i)^.*?(?:^|;[ ]*)((?:wp_woocommerce_session_[^=; ]+)=[^;]*).*$", "\1");
            }
        }

        # Remove UltraCache-only marker cookies before origin/hash.
        if (req.http.Cookie ~ "(?i)(^|;[ ]*)(esi_session|ultracache_esi_optin)=") {
            set req.http.Cookie = regsuball(req.http.Cookie, "(?i)(^|;[ ]*)(esi_session|ultracache_esi_optin)=[^;]*", "");
            set req.http.Cookie = regsuball(req.http.Cookie, "^[; ]+|[; ]+$", "");
            set req.http.Cookie = regsuball(req.http.Cookie, ";[ ]*;", ";");
            if (req.http.Cookie == "") { unset req.http.Cookie; }
        }

        # Woo shared-parent lookup requires the browser marker.
        if (req.http.Cookie ~ "(?i)(^|;[ ]*)(woocommerce_items_in_cart|woocommerce_cart_hash|wp_woocommerce_session_[^=; ]+)=") {
            if (req.http.X-UltraCache-ESI-Opt-In != "1") {
                set req.http.X-Cache-Mode = "PASS";
                return (pass);
            }
            set req.http.X-UltraCache-ESI-Cookie-Check = req.http.Cookie;
            set req.http.X-UltraCache-ESI-Cookie-Check = regsuball(req.http.X-UltraCache-ESI-Cookie-Check, "(?i)(^|;[ ]*)(woocommerce_items_in_cart|woocommerce_cart_hash|wp_woocommerce_session_[^=; ]+)=[^;]*", "");
            set req.http.X-UltraCache-ESI-Cookie-Check = regsuball(req.http.X-UltraCache-ESI-Cookie-Check, "^[; ]+|[; ]+$", "");
            if (req.http.X-UltraCache-ESI-Cookie-Check == "") {
                set req.http.X-UltraCache-ESI-Candidate = "1";
            } else {
                set req.http.X-Cache-Mode = "PASS";
                return (pass);
            }
            unset req.http.X-UltraCache-ESI-Cookie-Check;
        }
    } else if (
        req.url ~ "(?i)([?&])esi_scope=private(?:&|$)" &&
        req.url ~ "(?i)([?&])(ultracache_esi|ultracache_esi_probe_private_fragment)="
    ) {
        set req.http.X-ESI-Private-Request = "1";
        set req.http.X-ESI-Request-Level = "1";
        set req.http.X-Cache-Mode = "PASS";
        if (req_top.http.X-ESI-Original-Cookie) {
            set req.http.Cookie = req_top.http.X-ESI-Original-Cookie;
        } else {
            unset req.http.Cookie;
        }
        return (pass);
    } else {
        unset req.http.Cookie;
    }
}

sub vcl_hit {
    if (req.http.X-UltraCache-ESI-Candidate == "1" && obj.http.X-UltraCache-ESI-Shared-Parent != "1") {
        set req.http.X-Cache-Mode = "PASS";
        return (pass);
    }
}

sub vcl_backend_fetch {
    set bereq.http.Surrogate-Capability = "varnish=ESI/1.0";
    unset bereq.http.X-ESI-Original-Cookie;
    unset bereq.http.X-UltraCache-ESI-Cookie-Check;
    unset bereq.http.X-UltraCache-ESI-Opt-In;
    unset bereq.http.X-UltraCache-ESI-Shared-Parent;
}

sub vcl_backend_response {
    if (bereq.http.X-ESI-Private-Request == "1") {
        set beresp.ttl = 0s;
        set beresp.uncacheable = true;
        set beresp.http.Cache-Control = "private, no-store";
        set beresp.http.Surrogate-Control = "no-store";
        return (deliver);
    }

    if (bereq.http.X-UltraCache-ESI-Candidate == "1" && beresp.http.X-UltraCache-ESI-Shared-Parent != "1") {
        set beresp.ttl = 0s;
        set beresp.uncacheable = true;
        return (deliver);
    }

    if (beresp.status == 200 && beresp.http.Content-Type ~ "(?i)^text/html" && beresp.http.Surrogate-Control ~ "(?i)ESI/1[.]0") {
        set beresp.do_esi = true;
        unset beresp.http.Surrogate-Control;
    }
}
I need a ready solution for my Control Web Panel (CWP) server.

UltraCache CWP Varnish template: Use the bundled fail-closed template on CWP servers. Sites without the UltraCache request marker keep normal WooCommerce PASS behavior. On verified adapter pages, UltraCache approves only cached parents that contain the classic WooCommerce mini-cart ESI fragment.

The file preserves the CWP placeholders %domain%, %backend_domain%, %proxy_ip%, and %proxy_port%. Review the active include structure, rebuild affected domain configurations, compile/reload Varnish, and run Test Varnish.

Do third-party script matching rules load or contact those services?

No. Matching rules only identify scripts already added by the site, theme, or another plugin so UltraCache can apply delay, defer, or exclusion behavior.

Storage, troubleshooting and support11 questions
Why does the dashboard show zero page-cache files?

The cache may have just been flushed, no eligible anonymous public page may have been loaded yet, the requested page may be excluded, or the warm-up queue may not have completed.

Should I test public caching while logged in?

Use an anonymous or incognito window for public Page Cache testing. LCP Frontend Discovery can learn from anonymous visits while public discovery is active, or only from administrators when the administrator-only option is enabled.

Does clearing browser site data also clear UltraCache?

No. Browser storage and server-side UltraCache data are separate. Use Flush All Cache to clear the server-side caches managed by that action.

What should I check after changing optimization settings?

Open the main public pages and confirm that navigation, sliders, forms, product/cart actions, and page layout work normally and that no new browser-console errors appear.

Do I need to run Lighthouse after every normal content edit?

No. Lighthouse is most useful after initial setup or changes to the theme, optimization configuration, or major frontend components.

Can long-running jobs be resumed?

Supported batch operations use resumable queues. Use Start / Resume instead of recreating the entire job after an interruption.

What is the difference between cache counters and the actual cache state?

Dashboard counters summarize stored files and queue records. Recount or rebuild tools refresh those summaries when files or queue rows have changed outside the normal workflow.

Where can I get help?

Open Help for the installed version inside the UltraCache dashboard. For additional support, use the UltraCache support forum at https://wordpress.org/support/plugin/ultracache/.

Where are cache files stored?

Page-cache files are stored in ultracache/cache/ below the active WordPress uploads directory. Object-cache storage and generated optimization assets use dedicated directories below the same uploads/ultracache/ root.

What happens when UltraCache is deactivated or deleted?

The standard WordPress Plugins screen shows an UltraCache deactivation dialog where an administrator selects what should be retained if the plugin is later deleted. Available policies can retain settings and custom tables or remove plugin runtime/cache data. Converted media files are retained by design.

Does UltraCache send visitor data to an UltraCache-owned service?

No. UltraCache stores cache files, generated assets, settings, queue records, and troubleshooting information locally on the WordPress installation. Optional integrations contact only the services explicitly configured or opened by an administrator.

No matching FAQ entries.

Project links

Support, source, and release history

Use the WordPress.org support forum for help, GitHub for source and issue tracking, and the changelog for the complete release history.