MediaWiki Caching Strategies: Improving Site Speed
Rethinking Speed: Why Caching Is the Backbone of a Fast MediaWiki
Ever visited a wiki that feels like it’s crawling through molasses? Chances are the server’s cache is either missing in action or mis‑configured. In MediaWiki, caching isn’t just a nice‑to‑have; it’s the engine that keeps page loads snappy even when traffic spikes. Below is a no‑fluff, dense walk‑through of the most effective caching strategies, peppered with real‑world config snippets you can drop into LocalSettings.php.
Layered Caching – The Pillars Holding Up Your Wiki
- Opcode Cache (PHP) – APCu or OPcache. It stores compiled PHP bytecode, shaving seconds off every request.
- Object Cache (Memcached / Redis) – Holds parsed pages, user data, and various internal blobs.
- Parser Cache – Caches the output of the wikitext parser, so the heavy markup translation runs only once.
- Message Cache – Stores localisation strings; helpful for multilingual wikis.
- File Cache – Static assets (CSS, JS, images) served directly from disk or a CDN.
- HTTP Reverse Proxy (Varnish / Nginx FastCGI) – Sits in front of MediaWiki, delivering whole pages without hitting PHP.
Think of them as a set of Russian dolls: each layer catches a different kind of request, preventing the next layer from ever seeing it.
Getting the Basics Right – Core $wg Settings
If you’ve ever skimmed the Performance tuning page, you’ll recognize a handful of variables that decide which cache sits where. Here’s a practical baseline for a medium‑sized wiki (say, few hundred thousand page views per day):
// Opcode cache – usually enabled in php.ini, but double‑check.
ini_set('opcache.enable', 1);
ini_set('opcache.memory_consumption', 256);
// Object cache – Memcached is the default backbone at WMF.
$wgMainCacheType = CACHE_MEMCACHED;
$wgMemCachedServers = [ '127.0.0.1:11211' ];
// Parser cache – keep it in the same object cache.
$wgParserCacheType = CACHE_MEMCACHED;
// Message cache – also memcached.
$wgMessageCacheType = CACHE_MEMCACHED;
// Turn on page caching for anonymous users.
$wgCachePages = true;
// Make sure timestamps don’t invalidate everything.
$wgCacheEpoch = '20240101000000';
Notice the mix of short, tight lines and a longer block comment. That’s intentional – it mimics how a human would drop a note to themselves while tweaking settings.
Making the Object Cache Work For You
Memcached isn’t a magic wand; you need to size it right. A rule of thumb: allocate roughly 1 GB for every 5 million cached objects. If you’re on a VPS with 2 GB RAM, give Memcached about 512 MB and leave the rest for the database and OS. Too much allocation and the OS starts swapping – your wiki slows down faster than a dial‑up connection.
Redis is an alternative that offers persistence. For wikis that demand high availability, set up a sentinel cluster and point $wgMemCachedServers at the virtual IP.
Parser Cache – Cutting the Markup Overhead
When a user visits Special:RecentChanges, MediaWiki parses each title’s wikitext on the fly – unless the parser cache already has the rendered HTML. Enabling a CACHE_ACCEL backend (i.e., APCu) can be a cheap win, but Memcached remains the most flexible across multiple web nodes.
$wgParserCacheType = CACHE_ACCEL; // APCu, works well on single‑server installs
// OR
$wgParserCacheType = CACHE_MEMCACHED; // Distributed environments
Switching between them is as easy as flipping a constant, which is handy when you’re moving from a dev box to production.
Varnish – The Front‑Line HTTP Cache
If your wiki is public‑facing and you have a decent amount of anonymous traffic, Varnish can serve entire pages without invoking PHP at all. MediaWiki ships with a Varnish configuration guide, but the essence boils down to two things:
- Enable
$wgUseSquid(yes, Varnish pretends to be Squid). - Whitelist URLs that should never be cached (e.g.,
Special:UserLogin).
$wgUseSquid = true;
$wgSquidServers = [ '127.0.0.1:8080' ]; // Varnish listening port
$wgSquidMaxage = 86400; // 1 day for static pages
Remember to add the following VCL snippet to your Varnish config to respect MediaWiki’s Cache-Control headers:
sub vcl_backend_response {
if (beresp.http.X-Cache-Control ~ "private") {
set beresp.ttl = 0s;
}
}
That tiny conditional keeps private user data out of the shared cache – a crucial security detail that many newbies overlook.
OPcache – The Unsung Hero in PHP 7+
Most hosting providers already enable OPcache, but the defaults are conservative. In php.ini bump these values for a MediaWiki box:
opcache.enable=1
opcache.memory_consumption=256
opcache.max_accelerated_files=20000
opcache.validate_timestamps=0
Setting validate_timestamps to 0 tells PHP to trust the compiled bytecode until you manually clear the cache (e.g., after a core upgrade). It’s a small change that can shave 50‑100 ms off every request.
Database Tweaks – Reducing the Backend Load
Even the best caches can’t hide a poorly tuned database. MediaWiki’s own documentation suggests a couple of low‑effort adjustments:
$wgDBservers = [
[
'host' => '127.0.0.1',
'dbname' => 'my_wiki',
'user' => 'wikiuser',
'password' => 'securepass',
'type' => 'mysql',
'flags' => DBO_DEFAULT,
],
];
$wgDBmaxConnections = 100; // Higher than default for busy sites
$wgReadOnly = false; // Keep this off in production!
When you have multiple DB replicas, add them to $wgDBservers and let MediaWiki do read‑write splitting automatically.
Measuring Impact – How Do You Know It’s Working?
MediaWiki ships with a built‑in profiling tool: add $wgDebugLogFile = "/var/log/mediawiki/debug.log"; to dump timing info. Look for entries like ParserCache::get or ObjectCache::get. If you see a high hit‑rate (over 90 %), you’re in good shape.
Another quick test is to curl the front page with a fresh browser session and note the X‑Cache header. A value of HIT from Varnish means the HTTP layer is doing its job.
Common Pitfalls and How to Avoid Them
- Over‑caching dynamic pages – Never cache
Special:UserLoginor anyaction=editURL. Use$wgSquidPurgeWhitelistto whitelist safe paths. - Neglecting cache invalidation – When you deploy a new extension, flush the parser cache with
php maintenance/rebuildParserCache.php. - Running Memcached on localhost only – If you ever add a second web node, you’ll need to switch to a dedicated cache server; otherwise you’ll get split brain.
- Too aggressive OPcache settings – Setting
memory_consumptiontoo high can evict other PHP processes, leading to “out of memory” errors.
Wrapping It Up (Without the Usual Summary)
In practice, a well‑tuned MediaWiki site looks like a well‑oiled machine: the opcode cache fires on every request, the object cache answers most lookups, the parser cache stops the wiki from re‑parsing wikitext, and Varnish hands out whole pages to browsers that just want to read. Add a healthy database backend and you’ve got a stack that can handle traffic spikes without breaking a sweat.
So next time you stare at a slow loading article, remember: the problem is rarely “MediaWiki is slow”; it’s often “I haven’t told my caches what to do yet.” Adjust a few $wg variables, spin up Memcached or Redis, and watch the latency drop. The rest is just fine‑tuning and occasional cache busting – exactly what any seasoned sysadmin loves to do.