How to Fix Unupdated Sitemaps in Google Search Console: Improving with Last-Modified and 304 Responses
An issue occurred where the sitemap fetch date was not updating in Google Search Console (hereafter GSC), preventing new articles from being reflected in the index.
The site is operated on a WordPress + OpenLiteSpeed (LiteSpeed Cache plugin) environment. While the parent sitemap (sitemap.xml) was being fetched, monthly child sitemaps (e.g., sitemap-posttype-post.202508.xml) had not been updated since August 5th.
Since Bing Webmaster Tools was retrieving them normally, I deduced that the conditions related to Google’s crawling decisions and update detection were not being met.
Objective
-
Ensure GSC reliably detects updates to child sitemaps
-
Keep the sitemap fetch date updated and promote the indexing of new pages
-
Prevent future erroneous caching and missed update detections
Issues Identified Through Investigation
$ curl -I https://donguri3.net/sitemap-posttype-post.202508.xml HTTP/2 200 etag: "1924cd0be2d2a478d9675f0d7d647bd6" content-type: application/xml; charset=UTF-8 x-robots-tag: noindex, follow expires: Wed, 11 Jan 1984 05:00:00 GMT cache-control: no-cache, must-revalidate, max-age=0, no-store, private, no-store link: <https://donguri3.net/wp-json/>; rel="https://api.w.org/" vary: Accept-Encoding x-litespeed-cache: hit date: Sun, 10 Aug 2025 13:40:14 GMT server: LiteSpeed alt-svc: h3=":443"; ma=2592000, h3-29=":443"; ma=2592000, h3-Q050=":443"; ma=2592000, h3-Q046=":443"; ma=2592000, h3-Q043=":443"; ma=2592000, quic=":443"; ma=2592000; v="43,46"
-
Missing
Last-ModifiedHeader-
Google uses
Last-Modifiedas a reference for update detection, but it was not included in WordPress’s output.
-
-
Potential ETag Fixation
-
Due to LiteSpeed caching and plugin effects, ETags may not change even when the content changes.
-
-
Sitemaps Subject to LiteSpeed Cache
-
There was a risk that older XML would be returned due to cache hits.
-
-
Lack of Support for If-Modified-Since
-
Even when Googlebot sends conditional requests, it returns 200 every time instead of 304 Not Modified.
→ Results in wasteful re-fetches, leading to inefficient crawling.
-
Solutions
1. Exclude Sitemaps from Caching
In LiteSpeed Cache (LSCWP), go to Cache > Exclude and add the following to “Do Not Cache URIs".
/sitemap.xml /sitemap-*.xml /sitemap-posttype-*.xml /*sitemap*.xml
Additionally, added bypass rules to .htaccess or the OLS VHost Rewrite so that enabling caching in the future will not affect them.
# --- Completely bypass Sitemaps (prevent future erroneous caching) ---
RewriteCond %{REQUEST_URI} "(^/sitemap\.xml$|/sitemap-.*\.xml$|/.*sitemap.*\.xml$)"
RewriteRule .* - [E=cache-control:no-cache,E=cache-disable=1]
2. Implementing Last-Modified and 304 Responses
In functions.php, retrieve the last modified timestamp from the actual child sitemap data (the latest updated article of that month) and set it to Last-Modified.
Furthermore, compare it with If-Modified-Since, and if it is identical or newer, return 304 Not Modified.
add_action('init', function () {
$req = $_SERVER['REQUEST_URI'] ?? '';
if (!preg_match('#/(wp-sitemap|sitemap).*\.xml$#', $req)) return;
$lm_ts = null;
if (preg_match('#/sitemap-posttype-post\.(\d{4})(\d{2})\.xml$#', $req, $m)) {
$q = new WP_Query([
'post_type' => 'post',
'post_status' => 'publish',
'date_query' => [['year' => (int)$m[1], 'month' => (int)$m[2]]],
'orderby' => 'modified',
'order' => 'DESC',
'posts_per_page' => 1,
'no_found_rows' => true,
'fields' => 'ids',
]);
if (!is_wp_error($q) && !empty($q->posts)) {
$lm_ts = (int) get_post_modified_time('U', true, $q->posts[0]);
}
wp_reset_postdata();
}
if (!$lm_ts) $lm_ts = time() - 600;
$lm_http = gmdate('D, d M Y H:i:s', $lm_ts) . ' GMT';
header_remove('ETag');
header('Last-Modified: ' . $lm_http, true);
header('Cache-Control: no-cache, must-revalidate, max-age=0, no-store, private', true);
$ims_raw = $_SERVER['HTTP_IF_MODIFIED_SINCE'] ?? '';
$ims_ts = $ims_raw ? strtotime($ims_raw) : false;
if ($ims_ts !== false && $ims_ts >= $lm_ts) {
status_header(304);
http_response_code(304);
if (php_sapi_name() === 'cgi-fcgi') header('Status: 304 Not Modified', true);
header('Content-Length: 0');
exit;
}
}, 0);
3. Operation Verification
Header Check
curl -I https://blog.example.com/sitemap-posttype-post.202508.xml
-
Last-Modifiedmatches the actual last modification time -
No
ETag -
Cache-Controlset to no-cache
304 Response Check
LM="Sat, 02 Aug 2025 06:05:23 GMT" curl -I -H "If-Modified-Since: $LM" https://blog.example.com/sitemap-posttype-post.202508.xml
→ HTTP/2 304 Not Modified
Results
After the fix, I resubmitted the child sitemap whose fetching had stalled in GSC. After a short while, it displayed as “Success," and the last fetch date was updated.
Subsequently, new articles have been smoothly indexed as well.
Summary
-
The
Last-Modifiedheader is crucial for update detection -
Cache exclusion settings are mandatory (especially in LiteSpeed environments)
-
304 responses reduce wasteful crawls and improve update detection accuracy
-
When the “Last read" date in GSC does not update, review both server and application caching and header settings
With this response, Google’s crawling stabilized, and indexing speed improved.
If you are facing a similar issue where sitemaps are not updating in GSC, be sure to check your Last-Modified and cache control settings.