Skip to content

[6.x] Invalidate old static cache entries on entry URL changes - #15021

Merged
jasonvarga merged 3 commits into
statamic:6.xfrom
mynetx:fix/static-cache-old-slug
Sep 17, 2026
Merged

jasonvarga merged 3 commits into
statamic:6.xfrom
mynetx:fix/static-cache-old-slug

Conversation

@mynetx

@mynetx mynetx commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

When a static-cached entry's route changes — slug, date, or any other field the route references — the cache for the old URL was never invalidated . The old cached response kept being served instead of a redirect to the new URL.

This rebuilds the old URL from whichever route fields actually changed (via UrlBuilder, so it works with any route shape) and invalidates it, plus an /old-url/* wildcard so pages cached beneath it (children of a renamed parent, mounted collections) are cleaned up too. In background recache mode, old URLs are invalidated rather than refreshed, since they no longer resolve.

Fixes #14876

@mynetx
mynetx force-pushed the fix/static-cache-old-slug branch from b159368 to 26faed9 Compare July 22, 2026 07:01
@mynetx

mynetx commented Jul 22, 2026

Copy link
Copy Markdown
Contributor Author

Rebased onto 6.x to resolve the conflicts.

Since refresh() now delegates to invalidate(), I moved the old URL handling in there: when refreshing, the old URLs are invalidated separately (they 404 now, so they can't be recached), otherwise they get merged into the invalidateUrls() call as before. refresh() itself stays untouched, so the custom invalidator fix keeps working.

The invalidator only built URLs from the entry's current state, so after
a slug change the previously cached page kept being served at the old URL.
Rebuild the old URI from the original slug and invalidate it, along with
anything cached beneath it (descendants, mounted collections). In
background recache mode the old URLs are invalidated rather than
refreshed, since they no longer resolve and could never be recached.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@mynetx
mynetx force-pushed the fix/static-cache-old-slug branch from 26faed9 to 3abeb77 Compare September 15, 2026 21:13
@jasonvarga

Copy link
Copy Markdown
Member

This is "kinda" okay. It only solves the issue when a slug changes though. Other entry data can be in its url, and if that's the case and one of those values changes, you have the exact same bug.

I'm looking into a better solution.

jasonvarga and others added 2 commits September 17, 2026 10:48
getOldEntryUrls() only checked whether slug changed, so entries whose
route references other fields (eg. {year}/{month}/{day} from the date,
or a custom field) left stale cached pages when slug stayed the same.
Now every dirty route identifier is checked, and its original value is
substituted when rebuilding the old URL.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
… handling

getOldEntryUrls() compared its rebuilt old URL (via site()->url(), which
is relative on a default install) against the entry's current
absoluteUrl(), so the equality guard could never match and the old-vs-new
comparison silently degraded to invalidating URLs unnecessarily. Build
from site()->absoluteUrl() instead so both sides are comparable.

Also handle a literal {date} route identifier (not just {year}/{month}/{day})
by returning a Carbon instead of the raw dirty-state string, and pass the
original Carbon's timezone into createFromFormat() instead of assuming the
app timezone.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@jasonvarga

Copy link
Copy Markdown
Member

Pushed changes and updated the PR description. Thanks!

@jasonvarga jasonvarga changed the title [6.x] Fix old slug not removed from static cache when changing slugs [6.x] Invalidate an entry's old URL in the static cache when its url changes Sep 17, 2026
@jasonvarga jasonvarga changed the title [6.x] Invalidate an entry's old URL in the static cache when its url changes [6.x] Invalidate old static cache entries on entry URL changes Sep 17, 2026
@jasonvarga
jasonvarga merged commit 1b6caf9 into statamic:6.x Sep 17, 2026
64 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Old slug not removed from static cache when changing slugs

2 participants