Configuring Advanced Caching in MediaWiki for Better Performance
Getting a Grip on MediaWiki Caching
Imagine you’re running a community encyclopedia that spikes every time a hot topic lands on the front page. If each request has to rebuild the page from scratch, the server will choke faster than a smoker on a windy day. The good news? MediaWiki ships with a toolbox of caches, but they’re not set‑and‑forget. This post walks through the knobs you can turn, the back‑ends you can plug in, and a few human‑sized warnings that you’ll thank yourself for later.
Why Caching Matters (and isn’t just for big sites)
At the core, MediaWiki does three heavy lifts for every view:
- retrieving raw wikitext from the DB,
- running the parser to turn wikitext into HTML,
- serving the final HTML to the browser.
Each step can be cached. When done right, the server often serves a pre‑rendered page without ever touching MySQL. For a wiki with a few hundred daily hits, that can shave half a second off load time – a noticeable difference on slow mobile connections.
Pick Your Backend – Don’t Put All Eggs in One Basket
MediaWiki’s caching layer is abstracted through $wgMainCacheType and related variables. The choice of backend determines speed, scalability, and maintenance overhead.
Memcached – The Classic Choice
Memcached is memory‑only, distributed, and battle‑tested. If you already have a memcached cluster for other services, hooking MediaWiki into it is a breeze.
$wgMainCacheType = CACHE_MEMCACHED;
$wgMemCachedServers = [ "127.0.0.1:11211", "10.0.0.2:11211" ];
$wgParserCacheType = CACHE_MEMCACHED;
$wgMessageCacheType = CACHE_MEMCACHED;
Redis – When You Want Persistence and Pub/Sub
Redis adds a few goodies: TTL support, data structures, and optional disk persistence. Switch to it if you need to survive a reboot without dumping the cache.
$wgMainCacheType = CACHE_REDIS;
$wgRedisServers = [ "redis1.example.com:6379" ];
$wgRedisDatabase = 2; // keep it separate from other apps
APCu – Simple, Fast, Local
If your wiki lives on a single web node, APCu can be a “good enough” solution. It’s just an extension to PHP’s opcode cache, so you won’t need an extra daemon.
$wgMainCacheType = CACHE_ACCEL;
$wgCachePages = true; // make APCu store generated pages too
File‑Based Cache – The Last Resort
When you can’t install any extra service, MediaWiki can fall back to the filesystem. It’s slower, but still beats hitting the DB for every request.
$wgMainCacheType = CACHE_FILE;
$wgCacheDirectory = "/var/www/wiki/cache";
The Core Settings You’ll Tweak Most Often
Once the backend is set, these variables control what actually gets cached.
Object Cache – The Glue Across Extensions
The object cache is where extensions stash data like user preferences, recent changes, and API responses. Turn it on early; many extensions assume it exists.
$wgObjectCacheFactory = [
'class' => 'MediaWiki\\Cache\\CacheFactory',
'args' => [ $wgMainCacheType, $wgMemCachedServers ?? [] ]
];
Note: If you change the backend from file to memcached, you should clear $wgCacheDirectory manually once – otherwise old files linger and cause phantom cache hits.
Parser Cache – Save the HTML, Skip the Parser
The parser is a heavyweight beast. MediaWiki caches the parsed output per revision. By default it lives in the object cache, but you can force a separate store.
$wgParserCacheType = CACHE_MEMCACHED;
$wgParserCacheBackend = 'memcached';
$wgCachePages = true; // also store full page HTML
In a pinch, you can boost the hit rate by raising $wgRevisionCacheExpiry. Setting it to a week (604800 seconds) works for relatively static content.
Message Cache – Keep UI Text Fast
Every wfMessage() call reads from the DB unless you enable the message cache. It’s cheap to enable and gives a noticeable speed bump on heavily customized wikis.
$wgMessageCacheType = CACHE_MEMCACHED;
$wgMessageCacheExpiry = 86400; // 1 day
Page‑Level Caching – The Front Door
Even with a hot parser cache, generating the final HTML still takes a few milliseconds. MediaWiki’s “main cache” can store the entire page output.
- Enable it:
$wgCachePages = true; - Control TTL:
$wgCachePagesExpiry = 300;(seconds) - Skip for logged‑in users: set
$wgCachePages = falseinside aif ( $user->isAnon() )guard.
When you serve anonymous traffic through a CDN, you can offload that cached HTML to the edge. Just add a Cache‑Control: public, max‑age=300 header in LocalSettings.php:
$wgCachePages = true;
$wgCachePagesPurgeOnEdit = true;
$wgCachePagesUpdateOnPurge = true;
$wgExternalLinkTarget = '_blank'; // not a cache setting but often paired with CDN use
Fine‑Tuning for Real‑World Load
Now you have the big levers pulled. Below are a few knobs that make the difference between “good enough” and “solid as a rock”.
- Stash Backend:
$wgUseStash = true;If you have a Redis backend, MediaWiki can spill large objects into it, reducing PHP memory spikes. - Boost API Cache:
$wgAPIMaxCacheTTL = 60;helps with repeated API calls from bots. - Compress Cached Pages: Set
$wgCompressCachedPages = true;– tiny CPU cost, big bandwidth win.
Testing Your Setup – Don’t Guess, Measure
After you flip a setting, run php maintenance/rebuildmessages.php and php maintenance/rebuildparsercache.php to warm up the caches. Then, use a tool like ab or Jaeger to see response times.
A quick sanity check you can paste into a terminal:
for i in {1..10}; do curl -s -D - "https://wiki.example.com/Main_Page" | grep -i "X-Cache"; doneIf you see “X-Cache: HIT” (or “MISS” on the first run, then “HIT”), your cache is alive. If you get nothing, double‑check the memcached daemon is bound to the right interface and that $wgMemCachedPersistent is set to true for long‑lived connections.
Common Pitfalls (and How to Avoid Them)
- Mixing Backend Types: Don’t set
$wgMainCacheTypeto MEMCACHED but leave$wgParserCacheTypeat FILE. The mismatch forces one layer to fall back to disk, hurting performance. - Running Out of Memory: Memcached defaults to 64 MiB. For a busy wiki, you’ll want at least 256 MiB per node. Check with
memcached-tool stats. - Stale Content: Forgetting to purge the object cache after a bulk import leads to pages serving old revisions. Use
php maintenance/purgeList.phpafter big jobs. - ACL Issues: If your memcached server is exposed on the public internet, anyone can read cached pages. Bind it to
127.0.0.1or use firewall rules. - Wrong File Permissions: The cache directory must be writable by the web server user; otherwise MediaWiki silently falls back to “no cache”.
Wrapping Up – A Few Personal Takeaways
In my own little hobby wiki, I started with APCu because the host didn’t allow extra daemons. Once traffic grew, I migrated to Redis. The biggest surprise? Enabling $wgCompressCachedPages shaved ~0.3 s off the median load time, which felt like a win even though the wiki only served a few hundred visitors a day.
So, whether you’re running a corporate knowledge base or a fan‑run Star Trek wiki, give the cache a once‑over. The steps above aren’t rocket science, but they do require a bit of patience and a willingness to poke around in LocalSettings.php. A hands‑on approach will surface the quirks of your environment – and that’s where the real performance gains hide.
Happy caching!