Case Studies

Is Your WordPress Admin Slow? OPcache Might Be the Culprit

A common frustration with WordPress: the admin dashboard takes forever to load. You click a link, wait, wait some more. Plugin-heavy sites with WooCommerce, Elementor, Gravity Forms, and a dozen other tools are the worst offenders.

The usual suspects—slow hosting, too many plugins, unoptimized databases—get plenty of attention. But there’s a server-level setting that rarely comes up in WordPress performance guides, and it can make a dramatic difference.

The Problem We Found

While optimizing another nonprofit’s WordPress site, we noticed something unusual. The WordPress admin was taking over 11 seconds to load. Core PHP execution time—the time WordPress spends just bootstrapping itself before plugins and themes even run—was 3,137 milliseconds.

(We were able to find the core WordPress execution time—and that of plugins as well—by using the free Mochyon Lightspeed WordPress plugin.)

That’s over three seconds just to start up.

At this point in the optimization process, the site ran over 60 plugins, including WooCommerce, Elementor, Gravity Forms, and Jetpack. That’s a lot of PHP files. We counted over 6,000 that needed to load on every request.

What OPcache Does (and Why It Matters)

Every time PHP handles a request, it reads your PHP files from disk, compiles them into bytecode, and executes them. OPcache stores that compiled bytecode in memory so PHP doesn’t have to recompile thousands of files on every single page load.

Without OPcache (or with it misconfigured), your server is doing redundant work on every request—recompiling the same files over and over.

Most WordPress hosts enable OPcache by default. The problem is that the default settings were designed for much smaller applications.

Three Settings, One Big Impact

OPcache has three settings that matter most for WordPress:

opcache.memory_consumption — How much memory (in MB) is available for storing compiled scripts. The default is 128 MB. A large WordPress site with 60+ plugins can easily need 300–500 MB.

opcache.interned_strings_buffer — A separate memory pool for deduplicated strings (function names, class names, variable names). The default is 8 MB. When this fills up, strings spill into the main OPcache pool without deduplication, wasting enormous amounts of memory.

opcache.max_accelerated_files — The maximum number of scripts OPcache can store. The default is 10,000. A WooCommerce + Elementor site can easily exceed this.

The Diagnosis

Using a small PHP diagnostic script, we checked what was actually happening inside OPcache on the production server:

  • Hit rate: 49% — Half the files were being recompiled on every request. A healthy hit rate is 99%+.
  • Memory: completely full at the default allocation, with 0 bytes free.
  • Interned strings buffer: full at 8 MB. This was the critical finding. Only 52 MB of actual compiled bytecode was stored, but the interned strings overflow was consuming over 460 MB of the main pool—strings duplicated across thousands of scripts instead of being shared.
  • Only 3,924 of ~13,000 scripts cached. The rest were recompiled from disk on every request.

The Fix

We adjusted three values:

SettingBeforeAfter
opcache.memory_consumption128512
opcache.interned_strings_buffer864
opcache.max_accelerated_files1000020000

After a PHP-FPM restart, the results were immediate.

The Results

MetricBeforeAfterChange
Admin Page Load~11s~2s82% faster
WP Core Execution3,137ms1,016ms68% faster
OPcache Hit Rate49%99%+Scripts served from memory
Cached Scripts3,92413,000+All files cached

The admin went from painfully slow to responsive. No plugins were removed. No code was changed. The server was simply allowed to do its job properly.

How to Check Your Own Site

Create a temporary PHP file in your WordPress root (and delete it immediately after):

<?php
header("Content-Type: text/plain");
$s = opcache_get_status(false);
echo "Memory: " . number_format($s["memory_usage"]["used_memory"] / 1024 / 1024, 1)
   . " / " . number_format(($s["memory_usage"]["used_memory"] + $s["memory_usage"]["free_memory"]) / 1024 / 1024, 0) . " MB\n";
echo "Interned strings: " . number_format($s["interned_strings_usage"]["used_memory"] / 1024 / 1024, 1)
   . " / " . number_format($s["interned_strings_usage"]["buffer_size"] / 1024 / 1024, 0) . " MB\n";
echo "Scripts: " . number_format($s["opcache_statistics"]["num_cached_scripts"])
   . " / " . ini_get("opcache.max_accelerated_files") . "\n";
echo "Hit rate: " . number_format($s["opcache_statistics"]["opcache_hit_rate"], 1) . "%\n";
echo "OOM restarts: " . $s["opcache_statistics"]["oom_restarts"] . "\n";

Red flags to look for:

  • Hit rate below 95%
  • Memory nearly full (used ≈ total)
  • Interned strings buffer full
  • OOM restarts greater than 0
  • Cached scripts significantly lower than your actual file count

Important: Fetch this file through your browser, not via WP-CLI. OPcache runs inside PHP-FPM, and CLI has its own separate (usually disabled) OPcache.

Right-Sizing for Your Server

The values above worked for our site—60+ plugins on a server with 8 GB of RAM and plenty of headroom. Your site will be different. OPcache memory comes directly from your server’s RAM, so you need to make sure you have room before increasing these settings.

A few guidelines:

  • Check your available memory first. Run free -h on your server. If you’re already using most of your RAM, increasing OPcache allocations could starve PHP-FPM workers, MySQL, or your object cache. You need headroom, not just capacity.
  • Start with the diagnostic script. The numbers will tell you what your site actually needs. A 20-plugin site might be fine with 256 MB of memory_consumption and 32 MB of interned_strings_buffer. A 60-plugin WooCommerce site might need more.
  • Scale to your plugin count, not a magic number. The interned strings buffer is the most commonly undersized setting. If the diagnostic shows it full at 8 MB with high overhead in the main pool, try 32 MB or 64 MB. For memory_consumption, increase until your cached script count stabilizes and the hit rate climbs above 95%.
  • Shared servers add complexity. If your host runs multiple WordPress sites on the same PHP-FPM pool (common on platforms like Cloudways), they all share one OPcache. Your allocation needs to cover every site on the server, not just yours.
  • Smaller servers may need tradeoffs. On a 2 GB droplet, dedicating 512 MB to OPcache isn’t realistic. You might get more benefit from reducing your plugin count first, then optimizing OPcache for what remains.

The Catch: Changing These Settings

These are system-level settings, allocated once when PHP starts. They cannot be overridden by php_admin_value in your FPM pool config or by .htaccess—even though ini_get() will show the new value, the actual memory allocation won’t change.

They must be set in your server’s php.ini or OPcache module config file. On managed hosts like Cloudways, that means contacting support or using the platform’s PHP configuration panel.

If your host has multiple config files that set the same directive, the one that loads last wins. Ask your host to verify there are no conflicting values.

After changing the settings, PHP-FPM must be fully restarted (not just reloaded) for the new allocations to take effect.

Key Takeaway

WordPress performance problems are rarely mysterious. An 11-second admin page load sounds like a hosting problem or a plugin problem, but in this case it was a single-digit number in a config file. The server had enough CPU and RAM—it just wasn’t being allowed to use them effectively.

If you’re running a plugin-heavy WordPress site and the admin feels sluggish, check your OPcache settings before you start deactivating plugins. The right values depend on your site and server, but the diagnostic takes two minutes. You might be surprised how much performance is sitting on the table.