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 = false inside a if ( $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"; done

If 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)

  1. Mixing Backend Types: Don’t set $wgMainCacheType to MEMCACHED but leave $wgParserCacheType at FILE. The mismatch forces one layer to fall back to disk, hurting performance.
  2. 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.
  3. Stale Content: Forgetting to purge the object cache after a bulk import leads to pages serving old revisions. Use php maintenance/purgeList.php after big jobs.
  4. ACL Issues: If your memcached server is exposed on the public internet, anyone can read cached pages. Bind it to 127.0.0.1 or use firewall rules.
  5. 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!

Subscribe to MediaWiki Tips and Tricks

Don’t miss out on the latest articles. Sign up now to get access to the library of members-only articles.
jamie@example.com
Subscribe