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.
WordPress performance plugin
Make WordPress pages load faster, reduce server work, optimize images and frontend files, and keep every cache layer ready for visitors.
Features
UltraCache combines the main performance jobs in one place, so the site loads faster and cached content stays current.
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.
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.
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.
Replace original Media Library files and registered sizes with verified optimized versions while updating WordPress metadata, database references, and active theme CSS references.
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.
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.
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.
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.
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.
Work with LiteSpeed page cache, clear and refill the correct HTML variants, refresh stale pages, and keep the WordPress and server cache layers synchronized.
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.
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
Start with the recommended settings, prepare the first cache and image set, then check the public site in a private browser window.
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.
Help
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.
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.
No. Dynamic WooCommerce pages such as Cart, Checkout, and My Account are excluded from shared public page caching.
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.
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.
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.
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.
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.
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.
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.
Cache warm-up visits selected public URLs and creates their cache before a normal visitor opens them.
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.
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.
No. URLs are added to a controlled queue and processed according to the warm-up settings and available server resources.
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.
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.
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,avifWP-CLI runs as a foreground warm-up owner. A newer UI or WP-CLI warm-up takes ownership, while background cron work yields automatically.
No. Page warm-up and image conversion are separate operations. Use AVIF / WebP Batch Conversion to prepare existing Media Library images.
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.
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.
They control parallel execution separately for the Defer and Delay script groups. They are not first-party and third-party switches.
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.
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.
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.
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.
It combines generated local-font declarations and related font CSS into an optimized local resource.
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.
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.
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.
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.
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.
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.
Manual selectors take precedence over automatic LCP learning.
No. LCP Frontend Discovery learns from normal eligible visits while it is enabled. Lighthouse or PageSpeed can be used afterward to measure the result.
UltraCache records the text element and does not add an unrelated image preload for that mapping.
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.
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.
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.
The mapping has been confirmed, but the affected page is still waiting for its page cache to be rebuilt by the warm queue.
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.
AVIF usually produces smaller files. WebP provides broader compatibility with older software, image tools, and some hosting environments.
Yes. A common configuration is AVIF as the primary format and WebP as the fallback.
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.
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.
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.
No. SVG is a vector format and remains SVG.
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.
Not by itself. Enable Regen. existing and run the conversion process when existing AVIF or WebP files should be recreated with the current quality.
It processes existing Media Library images through the AVIF/WebP batch queue and continues an interrupted conversion from its saved progress.
It reconstructs the media-processing queue from the current Media Library and output policy. It is used when queue state is missing or inconsistent.
It recalculates the dashboard counts for existing optimized image files. It does not create new images.
It removes completed records from the media queue. It does not delete the generated AVIF/WebP files.
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.
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.
Yes. Its long-running stages persist progress and can pause, resume, or retry.
You can download and run WP-CLI inside your own hosting account. Root access is not required.
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 wpRun the following command and note the returned directory:
pwdYour WP-CLI executable will be located at:
/full/path/returned/by/pwd/wpRun:
find / \
-type f \
-name "php" \
-path "*/bin/*" \
-print \
2>/dev/nullThe 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.
Go to the directory containing wp-config.php and run:
pwdNote the full path returned by the command.
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=300The command processes the media queue using the website’s configured UltraCache image format and quality settings.
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.
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.
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.
SQLite is useful when Redis or APCu is unavailable, but its performance depends on storage speed and server concurrency.
WordPress loads the advanced-cache.php drop-in early so UltraCache can serve eligible page-cache responses before normal WordPress page generation.
WordPress uses the object-cache.php drop-in to replace the default runtime object cache with the selected persistent or advanced UltraCache backend.
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.
Yes. Flush All Cache clears the active UltraCache Object Cache as part of the full purge.
It reduces unnecessary WooCommerce cart processing when the visitor has no cart contents.
No. Customer-specific cart, checkout, account, and other excluded dynamic requests do not use the shared public page cache.
It postpones MailerLite nonce refresh work so it does not unnecessarily affect the initial cached page response.
Yes. UltraCache can vary cached pages by the active TranslatePress language so translated URLs do not share the wrong HTML cache.
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.
Yes. Configure and test the Varnish connection and purge details in the Varnish Cache section.
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.
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;
}
}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.
No. Matching rules only identify scripts already added by the site, theme, or another plugin so UltraCache can apply delay, defer, or exclusion behavior.
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.
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.
No. Browser storage and server-side UltraCache data are separate. Use Flush All Cache to clear the server-side caches managed by that action.
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.
No. Lighthouse is most useful after initial setup or changes to the theme, optimization configuration, or major frontend components.
Supported batch operations use resumable queues. Use Start / Resume instead of recreating the entire job after an interruption.
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.
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/.
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.
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.
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.
Project links
Use the WordPress.org support forum for help, GitHub for source and issue tracking, and the changelog for the complete release history.