Upgrading
Citizen serves CSS and JS fresh on every page view, but wikis cache HTML — in the parser cache, CDN or Varnish layers, and $wgUseFileCache. After an upgrade, cached pages generated by the old version meet the new styles, which can break their appearance until every cache has expired or been purged.
Start with the release cache status
Releases state a cache status in their notes, near the top and above the highlights — a one-line note, or a warning callout when a purge is needed. Check it first: it tells you whether the rest of this page applies at all.
| Status | What it means for you |
|---|---|
clean | No cached-HTML impact. Upgrade as usual — nothing else here applies. |
covered by compat | Follow the steps below so cached pages stay readable. |
purge required | Some pages cannot be bridged by styles alone, so plan a cache clear. The steps below still cover everything else. |
Older releases predate this convention. If the notes state no status, treat the release as covered by compat — or as purge required if they mention purging. Moving up several releases at once? Go with the strictest status of the bunch.
Plan ahead
If you know an upgrade is coming, lower $wgParserCacheExpireTime a few days early. It applies to entries already in the cache, not just new ones, so pages start re-parsing straight away and normal traffic works through the long tail before you deploy instead of after. Write the old value down first, and put it back once the upgrade has settled.
Upgrade steps
1. Turn the compat flag on
Set $wgCitizenCompat before you upgrade. It is safe to set on a version that predates it — nothing reads the setting until the new code is in place. While it is on, Citizen also serves the styles recent releases retired, so HTML cached by the old version keeps rendering acceptably — readable and usable, though not always pixel-perfect.
$wgCitizenCompat = true;How far back it reaches
The flag covers HTML generated by versions up to 6 minor releases back, which is roughly six months of releases at the current pace. The window is measured on the HTML, not on the size of your upgrade jump: what matters is the oldest version still sitting in your caches, and that is decided by your longest TTL. A 90-day CDN TTL can hold HTML from outside the window even on a one-release upgrade, and anything older than the window needs a cache clear.
2. Upgrade Citizen
Deploy the new version the way you normally would.
3. Purge, if the release asked for it
If the status is purge required, clear the cache now — after the upgrade, not before. Purging first achieves nothing, because those pages re-cache under the old version within minutes.
4. Let the old cache go
Stale pages last as long as the longest of these, counted from the deploy:
$wgParserCacheExpireTime— the parser cache. One day by default.$wgCdnMaxAge— how long a CDN or Varnish may serve a page. Five hours by default, though your CDN's own configuration can override it.$wgUseFileCachehas no expiry at all: entries stay until the page is edited or$wgCacheEpochmoves past them.
Leave the flag on for that long, or clear the cache if you would rather not wait.
Saving LocalSettings.php already moves the epoch
On a default wiki, $wgInvalidateCacheOnLocalSettingsChange pushes $wgCacheEpoch to the file's modification time. Save or touchLocalSettings.php after the upgrade and MediaWiki's own caches turn over from that moment, leaving only your CDN to wait for. Wikis that set that setting to false, or keep their config in a file LocalSettings.php merely includes, do not get this and need to set the epoch by hand.
5. Turn the flag off
Cached HTML carries the generation that rendered it, so you can check rather than guess. Purge any page with ?action=purge, view source, and note the data-mw-citizen-html attribute on <html>. Then open a page you know has not been edited since before the upgrade: if its attribute matches, that page is current.
Once the stale pages are gone, set $wgCitizenCompat = false; again. Leaving it on costs a few kilobytes of extra CSS and nothing else — the compat styles are written not to match current HTML — so wikis that deploy continuously can simply leave it on.
Clearing the old cache
Just one or two pages looking wrong? Purge those individually with ?action=purge and skip the rest of this section.
These clear MediaWiki's own caches
Nothing here touches a CDN or Varnish in front of your wiki. That needs its own purge, or its TTL to lapse — which is usually what decides when you can turn the flag off.
If your release is purge required, skip past the first option below: for those pages, waiting means leaving them visibly broken until they expire.
Just wait
Usually the right answer. Cached pages expire on their own, and the flag keeps them readable until they do, so there is nothing to run and no re-parse spike to absorb.
Move $wgCacheEpoch forward
Anything cached before the epoch is treated as stale, so pages re-parse as people visit them rather than all at once. This is also what clears the file cache, which has no expiry of its own, and it works with any parser cache backend rather than only CACHE_DB. Most wikis get it for free from saving LocalSettings.php (see step 4) — set it by hand if yours does not.
// The moment you upgraded, as a UTC MediaWiki timestamp
$wgCacheEpoch = '20260729120000';WARNING
This invalidates every page on the wiki, not just the ones Citizen's styles affect, so your whole hot set re-parses on first view. On a large or template-heavy wiki, pick a quiet window. The timestamp is UTC — a local one silently leaves hours of stale cache behind.
Purge the parser cache
Deletes entries outright, oldest first. --age is in seconds counted back from now, so pace a large purge by re-running it with a smaller age each day:
# Older than a week, then older than three days, then older than a day
php maintenance/run.php purgeParserCache --age 604800
php maintenance/run.php purgeParserCache --age 259200
php maintenance/run.php purgeParserCache --age 86400Add --dry-run to see what a run would delete before you commit to it — the deletion cannot be undone — and --msleep 500 to go easy on the database. If you lowered $wgParserCacheExpireTime per plan ahead, use --expiredate instead: --age assumes that setting has not changed.
WARNING
purgeParserCache.php only works when the parser cache is in the database — CACHE_DB, which is the default. If yours is in Memcached or Redis it stops with an error, so use $wgCacheEpoch instead.