{"id":348506,"date":"2026-08-04T13:53:48","date_gmt":"2026-08-04T13:53:48","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/abcode-cache-warmer\/"},"modified":"2026-08-04T13:53:35","modified_gmt":"2026-08-04T13:53:35","slug":"abcode-cache-warmer","status":"publish","type":"plugin","link":"https:\/\/wordpress.org\/plugins\/abcode-cache-warmer\/","author":22002451,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"1.1.0","stable_tag":"1.1.0","tested":"7.0.2","requires":"5.6","requires_php":"7.4","requires_plugins":null,"header_name":"ABCode Cache Warmer","header_author":"Ash Brentnall | ABCode","header_description":"Warm your WordPress cache after every purge. Crawls your posts, pages and archives in parallel, auto-tunes itself to your server, and tells you exactly which URLs were cached, so visitors never hit a cold page. Lightweight, fast, and free forever.","assets_banners_color":"9f9ea8","last_updated":"2026-08-04 13:53:35","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"","header_author_uri":"https:\/\/abcode.co.uk","rating":0,"author_block_rating":0,"active_installs":0,"downloads":35,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"1.1.0":{"tag":"1.1.0","author":"ashbrentnall","date":"2026-08-04 13:53:35"}},"upgrade_notice":[],"ratings":[],"assets_icons":{"icon-128x128.png":{"filename":"icon-128x128.png","revision":3634239,"resolution":"128x128","location":"assets","locale":"","width":128,"height":128},"icon-256x256.png":{"filename":"icon-256x256.png","revision":3634239,"resolution":"256x256","location":"assets","locale":"","width":256,"height":256}},"assets_banners":{"banner-1544x500.png":{"filename":"banner-1544x500.png","revision":3634239,"resolution":"1544x500","location":"assets","locale":"","width":1544,"height":500},"banner-772x250.png":{"filename":"banner-772x250.png","revision":3634239,"resolution":"772x250","location":"assets","locale":"","width":772,"height":250}},"assets_blueprints":{},"all_blocks":[],"tagged_versions":["1.1.0"],"block_files":[],"assets_screenshots":{"screenshot-1.png":{"filename":"screenshot-1.png","revision":3634239,"resolution":"1","location":"assets","locale":"","width":1200,"height":969},"screenshot-2.png":{"filename":"screenshot-2.png","revision":3634239,"resolution":"2","location":"assets","locale":"","width":1200,"height":809},"screenshot-3.png":{"filename":"screenshot-3.png","revision":3634239,"resolution":"3","location":"assets","locale":"","width":1200,"height":616},"screenshot-4.png":{"filename":"screenshot-4.png","revision":3634239,"resolution":"4","location":"assets","locale":"","width":1200,"height":791}},"screenshots":{"1":"The cache warmer, mid-run, showing per-URL cache results.","2":"Automatic server measurement and the settings it chose.","3":"Choosing which content gets warmed.","4":"Advanced settings for manual tuning."}},"plugin_section":[],"plugin_tags":[146,274437,274216,247,11676],"plugin_category":[52,54],"plugin_contributors":[233326],"plugin_business_model":[],"class_list":["post-348506","plugin","type-plugin","status-publish","hentry","plugin_tags-cache","plugin_tags-cache-preload","plugin_tags-cache-warmer","plugin_tags-performance","plugin_tags-preload","plugin_category-performance","plugin_category-security-and-spam-protection","plugin_contributors-ashbrentnall","plugin_committers-ashbrentnall"],"banners":{"banner":"https:\/\/ps.w.org\/abcode-cache-warmer\/assets\/banner-772x250.png?rev=3634239","banner_2x":"https:\/\/ps.w.org\/abcode-cache-warmer\/assets\/banner-1544x500.png?rev=3634239","banner_rtl":false,"banner_2x_rtl":false},"icons":{"svg":false,"icon":"https:\/\/ps.w.org\/abcode-cache-warmer\/assets\/icon-128x128.png?rev=3634239","icon_2x":"https:\/\/ps.w.org\/abcode-cache-warmer\/assets\/icon-256x256.png?rev=3634239","generated":false},"screenshots":[{"src":"https:\/\/ps.w.org\/abcode-cache-warmer\/assets\/screenshot-1.png?rev=3634239","caption":"The cache warmer, mid-run, showing per-URL cache results."},{"src":"https:\/\/ps.w.org\/abcode-cache-warmer\/assets\/screenshot-2.png?rev=3634239","caption":"Automatic server measurement and the settings it chose."},{"src":"https:\/\/ps.w.org\/abcode-cache-warmer\/assets\/screenshot-3.png?rev=3634239","caption":"Choosing which content gets warmed."},{"src":"https:\/\/ps.w.org\/abcode-cache-warmer\/assets\/screenshot-4.png?rev=3634239","caption":"Advanced settings for manual tuning."}],"raw_content":"<!--section=description-->\n<p>ABCode Cache Warmer is a cache warmer and cache preloader for WordPress. It rebuilds your page cache automatically after every purge, so no visitor is ever the one who waits for a cold, uncached page.<\/p>\n\n<p>Clearing your cache makes your site slow for a while. Every page has to be rebuilt from scratch, and it is your visitors who pay for it, the first person to land on each page waits for PHP and the database instead of getting a cached response. This plugin fixes that by visiting your pages for you, straight after a purge, so the cache is warm again before anyone real arrives.<\/p>\n\n<p>It works alongside any caching plugin or host cache: WP Rocket, LiteSpeed Cache, W3 Total Cache, WP Super Cache, WP Fastest Cache, Cache Enabler, Breeze, Nginx cache, Cloudflare, Kinsta, SiteGround and 20i StackCache among them. Your cache builds and serves pages; this plugin makes sure they are built before a visitor needs them.<\/p>\n\n<h4>Built to be fast<\/h4>\n\n<p>Most cache warmers request one URL at a time with a pause in between. On a site with a few hundred pages that leaves the cold-cache window open for many minutes, which is exactly the problem you were trying to solve.<\/p>\n\n<p>This plugin warms several URLs at once using the HTTP library already bundled with WordPress. No Composer, no vendor directory, no third-party HTTP client. Just a much shorter cold window.<\/p>\n\n<h4>It measures your server instead of guessing<\/h4>\n\n<p>There is no one-size-fits-all crawl speed. A VPS can take eight concurrent requests without noticing; cheap shared hosting cannot.<\/p>\n\n<p>On first load the plugin measures your site's real response time and combines it with your PHP memory limit, CPU count and current server load to pick safe settings automatically. While a run is in progress it keeps watching: if responses start slowing down it backs off on its own, and speeds back up when the server recovers. Every value stays manually adjustable.<\/p>\n\n<h4>It tells you whether it actually worked<\/h4>\n\n<p>Other warmers report HTTP 200 and call it a success. A 200 tells you the page loaded, not that it got cached.<\/p>\n\n<p>This plugin reads the cache headers on every response and reports what really happened for each URL:<\/p>\n\n<ul>\n<li><strong>Warmed<\/strong>: the page was not cached, and now it is<\/li>\n<li><strong>Cached<\/strong>: it was already warm, nothing to do<\/li>\n<li><strong>No cache<\/strong>: the page is deliberately uncacheable, such as a cart or checkout<\/li>\n<li><strong>Failed<\/strong>: shown with the actual error<\/li>\n<\/ul>\n\n<p>It recognises Cloudflare (including stale-while-revalidate states), LiteSpeed and QUIC.cloud, Varnish (by its transaction IDs), Fastly, CloudFront and Akamai, Sucuri, Nginx FastCGI and proxy caches, the standard Cache-Status header (RFC 9211), Kinsta, SiteGround, 20i's StackCache and StackCDN, Batcache (WordPress.com, Pressable, VIP), and (by their page signatures) WP Rocket, WP Super Cache, W3 Total Cache, WP Fastest Cache, Breeze and WP-Optimize.<\/p>\n\n<p>Where a host runs two layers, an origin cache on the server and a CDN edge in front of it, as 20i does, the layers are read outermost first, because a cached edge response carries frozen copies of the inner layer's headers from the moment the entry was built. A hit is credited to the layer that really served it, and a miss only counts once every layer outside it has also missed. So on 20i you will see Cached \/ StackCDN for pages the edge already held, and Warmed \/ StackCache for pages the warmer genuinely built.<\/p>\n\n<h4>Choose what gets warmed<\/h4>\n\n<ul>\n<li>Homepage<\/li>\n<li>Posts, pages and any public custom post type, all on by default<\/li>\n<li>Post type archives such as \/products\/ or \/portfolio\/, plus your blog page<\/li>\n<li>Category, tag and custom taxonomy archives<\/li>\n<li>Attachment pages<\/li>\n<li>Images referenced by the pages being warmed<\/li>\n<li>Your XML sitemap, core, Yoast or Rank Math<\/li>\n<li>Any extra URLs you add by hand<\/li>\n<\/ul>\n\n<h4>Warmed in the order that matters<\/h4>\n\n<p>URLs are not warmed in whatever order the database returns them. The homepage goes first, then archive landing pages, then content, and the whole queue is then ordered breadth-first, so shallower pages warm before deeper ones.<\/p>\n\n<p>On a site structured as \/accommodation\/ \u2192 \/accommodation\/cottages\/ \u2192 \/accommodation\/cottages\/rose-cottage\/, the parent pages get warmed first. They take the most traffic and they are usually the most expensive pages to rebuild, because they run listing queries. Within each level, the most recently updated content comes first.<\/p>\n\n<p>You can also skip URLs by pattern, with <code>*<\/code> as a wildcard, useful for carts, checkouts and account pages that should never be cached anyway.<\/p>\n\n<h4>About images<\/h4>\n\n<p>Warming raw image files is usually pointless, and this plugin does not push you into it. Image files are served straight off disk by your web server with no PHP involved, so there is no cold cache to prevent.<\/p>\n\n<p>There is one case where it genuinely helps: plugins that build each image on first request, such as ShortPixel Adaptive Images, Optimole, EWWW Easy IO, Jetpack or a WebP\/AVIF converter. There, the first visitor really does wait for the conversion.<\/p>\n\n<p>For that case the plugin takes a smarter route than crawling your media library. It reads the image URLs out of the HTML it has already downloaded while warming your pages, so it warms exactly the files (and exactly the responsive sizes) your live pages reference, rather than thousands of library items no page uses. Images are always queued behind every page, and capped per run so an image-heavy site cannot drown out the page warming.<\/p>\n\n<h4>Free forever<\/h4>\n\n<p>No URL limits. No locked features. No upsells. The whole plugin does the whole job.<\/p>\n\n<!--section=installation-->\n<ol>\n<li>Upload the plugin folder to <code>\/wp-content\/plugins\/<\/code>, or install it through the Plugins screen.<\/li>\n<li>Activate it.<\/li>\n<li>Go to <strong>Tools \u2192 Cache Warmer<\/strong>.<\/li>\n<li>Pick what to warm and press the button.<\/li>\n<\/ol>\n\n<!--section=faq-->\n<dl>\n<dt id=\"does%20this%20replace%20my%20caching%20plugin%3F\"><h3>Does this replace my caching plugin?<\/h3><\/dt>\n<dd><p>No. It works alongside whatever cache you already run. Your caching plugin builds and serves the cache; this plugin makes sure the cache exists before a visitor needs it.<\/p><\/dd>\n<dt id=\"do%20i%20need%20to%20leave%20the%20page%20open%3F\"><h3>Do I need to leave the page open?<\/h3><\/dt>\n<dd><p>No. While the tab is open the browser drives the run, which is the fastest option and gives you live results. Close the tab and WP-Cron takes over, so the run keeps going in the background. Come back later and the page picks up exactly where it got to, you never have to start again.<\/p>\n\n<p>Background progress depends on WP-Cron. The Schedule tab checks whether cron is actually being serviced rather than guessing from configuration: DISABLE_WP_CRON with a server cron running wp-cron.php (the setup most managed hosts use) is reported as healthy, and a warning only appears when scheduled tasks are genuinely overdue and nothing is firing them.<\/p><\/dd>\n<dt id=\"can%20it%20warm%20on%20a%20schedule%3F\"><h3>Can it warm on a schedule?<\/h3><\/dt>\n<dd><p>Yes. The Schedule tab runs warming every hour, twice a day, daily or weekly, using whichever sources you picked on the Warmer tab. Daily, twice-daily and weekly runs fire at a time you choose, in your site's timezone (most sites want the early hours, so 3am is the default) and weekly runs on the day you pick. Twice-daily runs at the two times you choose, they need not be twelve hours apart.<\/p>\n\n<p>Purge-triggered warming deliberately has no quiet-hours setting: a purge means the cache is cold right now, and making visitors wait until 3am for warm pages would defeat the point. The load-aware throttling is what keeps that immediate response polite.<\/p><\/dd>\n<dt id=\"does%20it%20warm%20automatically%20when%20i%20clear%20my%20cache%3F\"><h3>Does it warm automatically when I clear my cache?<\/h3><\/dt>\n<dd><p>Yes, and it is on out of the box, that is the whole point of the plugin. Clear your cache and, a minute later, the warmer starts rebuilding it, so the cold window closes before your visitors find it.<\/p>\n\n<p>It listens for the purge actions fired by WP Rocket, LiteSpeed Cache, W3 Total Cache, WP Super Cache, WP Fastest Cache, Cache Enabler, SiteGround Optimizer, Breeze, Hummingbird, WP-Optimize, Nginx Helper and Autoptimize. The Schedule tab shows which of those it found on your site.<\/p>\n\n<p>StackCache on 20i hosting is fully supported, by a different route: it fires no purge action of its own, so the warmer hooks the exact events its source purges on. A full purge, switching theme, saving the Customiser, activating or deactivating a plugin, or pressing StackCache's own Purge Cache button in the admin bar or its settings page, triggers a full warm. Its single-page purges are matched with single-page warms: the publish trigger covers edits, and an approved comment re-warms just the page it landed on.<\/p>\n\n<p>Purges that announce themselves are caught instantly. For the ones that do not, StackCache's own purge button, a host clearing the cache at server level, an eviction, a watchdog checks the cache every ten minutes by fetching your homepage and reading the same cache headers the warmer reads. A cold homepage alone is never trusted as proof of a full purge: the watchdog confirms against sentinel pages spread across the site, saved from your last run. Only a quorum of them also being cold starts a full warm, a single purged or evicted page stays a local event, and the checks themselves will have re-warmed it. However the cache gets emptied, the cold window is minutes, not until the next schedule.<\/p>\n\n<p>Using something else? Any cache that fires an action when it clears can be wired in with one line:<\/p>\n\n<pre><code>add_filter( 'abcw_purge_hooks', function ( $hooks ) { $hooks[] = 'my_cache_cleared'; return $hooks; } );\n<\/code><\/pre><\/dd>\n<dt id=\"can%20i%20see%20what%20was%20warmed%20after%20the%20fact%3F\"><h3>Can I see what was warmed after the fact?<\/h3><\/dt>\n<dd><p>Yes. The Results tab lists every retained run (when it ran, what triggered it, and how it went) and each one expands to its full per-URL results: what happened to every URL, which cache layer answered, and the time of day it was warmed. Every URL is a link that opens in a new tab, so chasing down a failure is one click. The newest run opens itself.<\/p>\n\n<p>You choose how long runs are kept, in Advanced settings: an age in days and a maximum count. Retention is rolling, each stored run drops off individually as it passes the age you set, rather than being wiped in bulk. Nothing here needs a database table.<\/p><\/dd>\n<dt id=\"what%20happens%20when%20only%20one%20page%20is%20cleared%3F\"><h3>What happens when only one page is cleared?<\/h3><\/dt>\n<dd><p>Only that page gets warmed. Fixing a typo clears one page, so recrawling the whole site would be absurd, the warmer just re-requests the page that went cold, as a single request, entirely separately from the full-run machinery. Only a site-wide purge starts a full run.<\/p>\n\n<p>Publishing works the same way: it warms the post plus the pages that list it, your homepage, its post type archive, and your blog page if you use a static front page. An approved comment (which most page caches silently purge the post for) re-warms just that one page, under the same setting. Targeted warms are logged on the Results tab like any run, bucketed by the hour, so what was re-warmed after each edit stays answerable.<\/p>\n\n<p>The publish trigger matters most on hosts whose cache clears edited pages silently, such as StackCache on 20i: there is no purge action to hear, so without the publish trigger a saved post simply stays cold until something else warms it.<\/p><\/dd>\n<dt id=\"what%20stops%20it%20warming%20over%20and%20over%3F\"><h3>What stops it warming over and over?<\/h3><\/dt>\n<dd><p>Two things. A burst of purges (a bulk edit fires one per post) folds into the single run already waiting, and a five minute cooldown stops a site that purges constantly from crawling itself back to back. The wait before warming is adjustable on the Schedule tab, and the cooldown is filterable with <code>abcw_auto_cooldown<\/code>.<\/p><\/dd>\n<dt id=\"what%20happens%20if%20my%20server%20rate%20limits%20the%20warmer%3F\"><h3>What happens if my server rate limits the warmer?<\/h3><\/dt>\n<dd><p>The warmer backs off and retries, rather than ploughing on. An HTTP 429 is treated as an instruction, not a failure: the refused URLs go back on the queue for up to two more attempts, the crawl drops to one request at a time with a full second between, and the run stands down for the server's Retry-After window (a minimum of thirty seconds) before trying again. A URL still refused after three attempts is marked failed with a note suggesting lower concurrency. Instantly rejected requests are also kept out of the speed measurements, so a burst of rejections cannot trick the adaptive throttle into thinking the server is fast.<\/p><\/dd>\n<dt id=\"will%20this%20inflate%20my%20analytics%3F\"><h3>Will this inflate my analytics?<\/h3><\/dt>\n<dd><p>Google Analytics, Matomo, Plausible, Fathom and anything else JavaScript-based will not see the warmer at all. Those tools count a visit when their script runs in a browser; the warmer downloads HTML and never executes JavaScript, so no tracking ever fires. It cannot trigger ad impressions for the same reason.<\/p>\n\n<p>Server-side counters are the exception. Tools that count visits in PHP or from server logs (WP Statistics, log analysers, hosting bandwidth graphs) will see the warming requests, and only on cache misses, since a cache hit never reaches PHP. To make filtering easy, every warming request carries a <code>DNT: 1<\/code> header, which privacy-respecting analytics plugins already honour, and an <code>X-ABCode-Cache-Warmer<\/code> header that log tooling can exclude on. The <code>abcw_request_headers<\/code> filter adjusts them.<\/p><\/dd>\n<dt id=\"will%20this%20slow%20my%20site%20down%3F\"><h3>Will this slow my site down?<\/h3><\/dt>\n<dd><p>Warming adds no work overall. Every cold page has to be rendered exactly once by somebody, warming only decides that it is the warmer that waits for it rather than a visitor, and lets you choose when. The only genuinely extra work is rendering pages nobody would have visited before the cache expired anyway.<\/p>\n\n<p>While a run is going, the load it adds is simply your concurrency setting: five concurrent requests is five simultaneous visitors, no more. Everything else the plugin does is rounding error next to that.<\/p>\n\n<p>It is also careful about when it does it. Before every batch it checks both how fast your site is responding and how loaded the machine actually is, and scales itself down accordingly, down to a single request at a time, and to a complete standstill if the server is genuinely struggling, resuming once it recovers. Those are two different signals on purpose: on shared hosting the box can be flat out serving someone else while your site still answers quickly.<\/p>\n\n<p>The one thing it cannot see is how many PHP workers your host gives you. If that number is small, set the concurrency by hand: 2 on entry-level shared hosting, 4 or 5 on a decent VPS, 8 or more on a dedicated server.<\/p><\/dd>\n<dt id=\"is%20a%20repeat%20run%20as%20expensive%20as%20the%20first%3F\"><h3>Is a repeat run as expensive as the first?<\/h3><\/dt>\n<dd><p>No, far cheaper. An already-warm page returns a cache hit that never touches PHP, so a scheduled run over a warm site costs a fraction of the first crawl. The expensive case is a run straight after a full purge, when everything is cold, which is exactly why the automatic run waits before it starts, and why on a large site it is worth pushing that wait up to several minutes.<\/p><\/dd>\n<dt id=\"why%20is%20ssl%20verification%20off%20by%20default%3F\"><h3>Why is SSL verification off by default?<\/h3><\/dt>\n<dd><p>Local and staging sites very often use self-signed certificates, and verification would make every request fail there. The plugin only ever requests URLs on your own domain, so this is low risk, but you can turn verification on in Advanced settings.<\/p><\/dd>\n<dt id=\"should%20i%20warm%20my%20images%3F\"><h3>Should I warm my images?<\/h3><\/dt>\n<dd><p>Probably not. Warming a page caches that page's HTML, it does not fetch the images on it, because only a real browser does that. If your images are ordinary files, your web server sends them without touching PHP and there is nothing to warm.<\/p>\n\n<p>Turn images on only if you run a plugin that generates images on first request (ShortPixel Adaptive Images, Optimole, EWWW Easy IO, Jetpack, or a WebP\/AVIF converter). On a site with many thousands of images, warm the pages and leave images off.<\/p><\/dd>\n<dt id=\"some%20urls%20report%20%22no%20cache%22%2C%20is%20that%20a%20problem%3F\"><h3>Some URLs report \"No cache\", is that a problem?<\/h3><\/dt>\n<dd><p>No. It means the page is intentionally excluded from caching, which is correct behaviour for carts, checkouts, account pages and anything personalised. Add those to the skip list to keep them out of future runs.<\/p><\/dd>\n<dt id=\"does%20it%20work%20with%20a%20page%20builder%20%2F%20woocommerce%20%2F%20multisite%3F\"><h3>Does it work with a page builder \/ WooCommerce \/ multisite?<\/h3><\/dt>\n<dd><p>Yes. Any public post type is warmable. On WooCommerce, add <code>\/cart\/<\/code>, <code>\/checkout\/<\/code> and <code>\/my-account\/*<\/code> to the skip list. On multisite, each site has its own settings and runs independently.<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>1.1.0<\/h4>\n\n<ul>\n<li>Automatic warming the moment your cache is cleared, with built-in support for WP Rocket, LiteSpeed Cache, W3 Total Cache, WP Super Cache, WP Fastest Cache, Cache Enabler, SiteGround Optimizer, Breeze, Nginx Helper and Autoptimize.<\/li>\n<li>StackCache (20i) support, verified against its source: the exact events it purges everything on, plus instant detection of its own Purge Cache button in both the admin bar and its settings page. Approved comments (which silently purge the commented page) re-warm that page under the publish trigger.<\/li>\n<li>A cache watchdog: every ten minutes the homepage's cache headers are checked, and a cold result is confirmed against sentinel pages across the site before a full warm is started, catching purge buttons, server-level clears and evictions that no WordPress hook announces, without ever launching a site-wide crawl over one cold page.<\/li>\n<li>Single-page purges warm just that page instead of starting a full run.<\/li>\n<li>Publishing warms the post plus the pages that list it, rather than the whole site.<\/li>\n<li>Load-aware throttling: server load is checked before every batch, scaling concurrency down and pausing the run outright when the machine is under real pressure.<\/li>\n<li>Optional trigger for when content is published or updated.<\/li>\n<li>New Results tab: every retained run is kept in full and expands to its complete per-URL results, with a warmed-at time against every URL and each URL clickable in a new tab. Retention is rolling and yours to set, an age in days and a maximum run count, with old runs dropping off one at a time as they expire.<\/li>\n<li>Select all \/ Clear all for the warming sources.<\/li>\n<li>Repeat purges fold into one run, with an adjustable delay and a cooldown so a busy site cannot crawl itself back to back.<\/li>\n<li>Results now appear one URL at a time as each response lands, rather than a batch at a time.<\/li>\n<li>Scheduled runs now fire at chosen clock times in the site's timezone, daily at a time you pick, twice daily at two independent times, weekly on a chosen day, instead of whenever the setting happened to be saved.<\/li>\n<li>The WP-Cron notice now measures instead of assumes: DISABLE_WP_CRON with a working server cron is reported as the healthy setup it is, and the warning is reserved for cron queues that are genuinely overdue.<\/li>\n<li>Rate limiting (HTTP 429\/503) is now handled properly: refused URLs are retried after the server's Retry-After window instead of being written off, the crawl drops to a gentle single request while limited, and a run can no longer burn through its queue at full speed against a server that is rejecting everything instantly.<\/li>\n<li>Broader cache detection: Varnish transaction IDs, Batcache, Sucuri, QUIC.cloud, the standard RFC 9211 Cache-Status header, Cloudflare's stale\/updating\/revalidated states, and page signatures for WP Fastest Cache, Breeze and WP-Optimize. Origin-level hits are no longer masked by an edge cache reporting a miss in front of them.<\/li>\n<li>Purge listening added for Hummingbird and WP-Optimize, and the LiteSpeed purge hooks corrected to the names LiteSpeed actually uses.<\/li>\n<li>Cache layers are now detected outermost-first, so an edge hit is no longer misread as a fresh warm just because it carries the origin's frozen MISS header from when the entry was built. Affected 20i (StackCDN over StackCache) and Cloudflare-over-LiteSpeed setups.<\/li>\n<li>StackCache and StackCDN cache headers are now read properly, so 20i sites report real hit\/miss results instead of assuming every response was a fresh render.<\/li>\n<li>The adaptive throttle no longer mistakes heavy pages for a struggling server. Its response-time baseline now drifts with the site instead of being frozen at the first batch, a run that starts on light pages and reaches a heavy section backs off briefly, re-baselines, and comes back to full speed, instead of crawling the rest of the site at one URL at a time.<\/li>\n<li>A run on a busy shared server no longer stalls indefinitely: after a few attempts at waiting for the load to drop, it crawls at one URL at a time rather than never finishing.<\/li>\n<li>Page builder template post types (Elementor, Beaver Builder, Divi, Oxygen, Brizy) are no longer offered as warming sources at all: their URLs are editor machinery, and rendering one outside its context caches a junk entry. Post format archives and builder taxonomies are gone for the same reason. Anything exotic can still be warmed via the manual include list, and <code>abcw_internal_post_types<\/code> \/ <code>abcw_internal_taxonomies<\/code> filters adjust the exclusions.<\/li>\n<li>Attachment Pages only appear as a source on sites where WordPress actually serves attachment pages, since WordPress 6.4 a fresh install redirects them to the file, leaving nothing to warm.<\/li>\n<li>A run that finds no cache headers at all now says so, instead of quietly reporting every URL as warmed.<\/li>\n<li>Database writes during a run cut by around three quarters: the live row log is stored apart from the run's counters, and the permanent record is written once per batch instead of once per chunk.<\/li>\n<li>Long runs no longer stop reporting when the page's security token expires, each progress response carries a fresh one.<\/li>\n<li>Requires WordPress 5.6 or newer, which was already true in practice; the header now says so.<\/li>\n<li>Fixed: a schedule was silently lost when the plugin was deactivated and reactivated; the saved setting now rebuilds its cron event automatically.<\/li>\n<li>Fixed: a queued single-page warm could be lost if the server killed the request part-way; the queue now survives and is finished by the next trigger.<\/li>\n<li>Fixed: the last rows of a run could be lost, and the progress bar stop a URL short of 100%, because the run record was deleted the instant it finished.<\/li>\n<li>Fixed: rows could appear twice on a slow site, when progress requests overlapped each other.<\/li>\n<li>Fixed: URLs containing <code>.\/<\/code> or doubled slashes warmed the same page twice under two different addresses.<\/li>\n<li>Warming requests now carry <code>DNT: 1<\/code> and an <code>X-ABCode-Cache-Warmer<\/code> header, so server-side analytics can filter them out. JavaScript analytics such as Google Analytics never saw them anyway.<\/li>\n<li>New <code>abcw_purge_hooks<\/code>, <code>abcw_purge_post_hooks<\/code>, <code>abcw_auto_cooldown<\/code>, <code>abcw_load_steps<\/code>, <code>abcw_internal_post_types<\/code>, <code>abcw_internal_taxonomies<\/code> and <code>abcw_request_headers<\/code> filters.<\/li>\n<li>Renamed the admin menu entry to Cache Warmer.<\/li>\n<\/ul>\n\n<h4>1.0.0<\/h4>\n\n<ul>\n<li>Initial release.<\/li>\n<li>Parallel cache warming with no third-party dependencies.<\/li>\n<li>Automatic server measurement and adaptive throttling.<\/li>\n<li>Per-URL cache hit\/miss reporting across major caching layers.<\/li>\n<li>URL sources for posts, pages, custom post types, post type archives, taxonomies, attachment pages and XML sitemaps.<\/li>\n<li>Optional image warming, discovered from the pages being crawled and capped per run.<\/li>\n<li>Breadth-first hierarchy ordering so parent pages warm before their children.<\/li>\n<li>Live results, each URL appears in the table the moment it finishes.<\/li>\n<li>Runs continue in the background via WP-Cron when you close the tab, and resume where they left off.<\/li>\n<li>Scheduled warming: hourly, twice daily, daily or weekly.<\/li>\n<li>Tabbed interface: Warmer, Results, Schedule and Advanced.<\/li>\n<li>Manual include and wildcard skip lists.<\/li>\n<li>Working stop button.<\/li>\n<\/ul>","raw_excerpt":"Automatic cache warmer and preloader: rebuilds your page cache after every purge, in parallel, and shows exactly which URLs were cached.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/348506","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=348506"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/ashbrentnall"}],"wp:attachment":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=348506"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=348506"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=348506"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=348506"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=348506"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=348506"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}