2026年11月12日

2026年11月12日

WordPress OPcache on PHP-FPM: Settings, Status Checks and Clearing

This article is a localized edition of the Japanese original. Read the Japanese original

OPcache stores the compiled form of PHP scripts (opcodes) in shared memory so that later requests can skip compilation. WordPress loads hundreds of PHP files for every page view, so whether OPcache is enabled and whether it has enough memory makes a real difference to response times.

This article shows how to check and configure OPcache for the PHP-FPM that runs WordPress. Paths follow Ubuntu 24.04 (PHP 8.3) as of October 2026. For other versions, replace 8.3 accordingly.

The command line and PHP-FPM have separate settings

The first thing to know is that the php command (CLI) and PHP-FPM (the web side) read separate configuration files and keep separate caches.

Configuration directory (Ubuntu) OPcache default
CLI (php, WP-CLI) /etc/php/8.3/cli/ opcache.enable_cli=0 (off)
PHP-FPM (web) /etc/php/8.3/fpm/ opcache.enable=1 (on)

So if you check the status from the CLI, for example with php -r 'var_dump(opcache_get_status());', you will normally just get false (disabled), which tells you nothing about the web side. For the same reason, running wp eval 'opcache_reset();' only clears the CLI cache; the PHP-FPM cache stays as it is.

Check whether OPcache is enabled in PHP-FPM

You can see the settings PHP-FPM has loaded with this command:

php-fpm8.3 -i | grep -E '^opcache\.(enable|memory_consumption|interned_strings_buffer|max_accelerated_files|validate_timestamps|revalidate_freq|jit) '

In the WordPress admin, "Tools → Site Health → Info → Server" also shows the PHP version and SAPI, but not OPcache usage (free memory or hit rate). To see usage, you have to call opcache_get_status() on the web side.

A small plugin that shows usage in the admin

Save the following file as wp-content/mu-plugins/opcache-status.php and usage appears under "Tools → OPcache Status". Only administrators (users with the manage_options capability) can see it. Feel free to delete it once you are done checking.

<?php
/**
 * Plugin Name: OPcache Status (admin screen)
 */
add_action( 'admin_menu', function () {
	add_management_page( 'OPcache Status', 'OPcache Status', 'manage_options', 'opcache-status', function () {
		if ( ! function_exists( 'opcache_get_status' ) ) {
			echo '<div class="wrap"><p>The OPcache extension is not loaded.</p></div>';
			return;
		}
		$s = opcache_get_status( false );
		if ( ! $s ) {
			echo '<div class="wrap"><p>OPcache is disabled, or calls are restricted by opcache.restrict_api.</p></div>';
			return;
		}
		$mb   = 1024 * 1024;
		$mem  = $s['memory_usage'];
		$st   = $s['opcache_statistics'];
		$str  = $s['interned_strings_usage'];
		$rows = array(
			'Used memory (MB)'          => round( $mem['used_memory'] / $mb, 1 ),
			'Free memory (MB)'          => round( $mem['free_memory'] / $mb, 1 ),
			'Wasted memory (%)'         => round( $mem['current_wasted_percentage'], 2 ),
			'String buffer used/total (MB)' => round( $str['used_memory'] / $mb, 1 ) . ' / ' . round( $str['buffer_size'] / $mb, 1 ),
			'Cached scripts'            => $st['num_cached_scripts'],
			'Keys / limit'              => $st['num_cached_keys'] . ' / ' . $st['max_cached_keys'],
			'Hit rate (%)'              => round( $st['opcache_hit_rate'], 2 ),
			'Restarts (out of memory)'  => $st['oom_restarts'],
			'Restarts (out of keys)'    => $st['hash_restarts'],
			'Full (cache_full)'         => $s['cache_full'] ? 'yes' : 'no',
		);
		echo '<div class="wrap"><h1>OPcache Status</h1><table class="widefat striped"><tbody>';
		foreach ( $rows as $label => $value ) {
			printf( '<tr><th>%s</th><td>%s</td></tr>', esc_html( $label ), esc_html( (string) $value ) );
		}
		echo '</tbody></table></div>';
	} );
} );

These are the items to look at:

Item Condition Action
Free memory Close to 0, and cache_full is "yes" Increase opcache.memory_consumption
String buffer Usage close to the total Increase opcache.interned_strings_buffer
Keys / limit Close to the limit, and "Restarts (out of keys)" keeps rising Increase opcache.max_accelerated_files
Restarts (out of memory) Not 0 Increase opcache.memory_consumption

The hit rate is low right after PHP-FPM starts or the cache is cleared. Check it after the site has been running for a while.

Choose the values

Here are the defaults of the main settings (from the PHP manual) and reasonable values for WordPress.

Setting Default Guideline
opcache.memory_consumption 128 (MB) 128 to 256. If you have many plugins or run several sites on the same PHP-FPM, increase it based on the usage figures above
opcache.interned_strings_buffer 8 (MB) Around 16. Adjust based on usage
opcache.max_accelerated_files 10000 More than the number of PHP files on the site. The actual limit is the smallest prime at or above the value you set (223, 463, 983, 1979, 3907, 7963, 16229, 32531, 65407 …)
opcache.validate_timestamps 1 See "Checking for file changes" below
opcache.revalidate_freq 2 (seconds) With validate_timestamps=1, how often (in seconds) files are checked for changes
opcache.save_comments 1 Leave it at 1. Setting it to 0 breaks libraries that read doc comments

Count the PHP files like this. If several sites share the same PHP-FPM pool, use the total for all of them.

find /var/www -type f -name '*.php' | wc -l

Put the settings in a new file that only FPM reads. /etc/php/8.3/mods-available/opcache.ini is read by both the CLI and FPM, so don't use it here.

; /etc/php/8.3/fpm/conf.d/99-opcache-wordpress.ini
opcache.enable=1
opcache.memory_consumption=192
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=20000
opcache.validate_timestamps=1
opcache.revalidate_freq=60

Apply the change and confirm the new values:

sudo php-fpm8.3 -t
sudo systemctl reload php8.3-fpm
php-fpm8.3 -i | grep -E '^opcache\.(memory_consumption|max_accelerated_files|revalidate_freq) '

Watch out for settings from older articles

Setting Current status
opcache.fast_shutdown Removed in PHP 7.2.0. It has no effect (the equivalent behavior happens automatically)
opcache.cache_id Windows only. It lets processes with the same user, the same SAPI and the same ID share a cache; it has nothing to do with how files with errors are handled
opcache.enable_cli=1 CLI runs end after each command, so it usually doesn't speed anything up. Leave the default of 0

Checking for file changes (validate_timestamps)

With opcache.validate_timestamps=1 (the default), OPcache checks file modification times every revalidate_freq seconds and recompiles files that changed. With revalidate_freq=60, old code can run for up to 60 seconds after you change a file, but the checks happen less often.

With opcache.validate_timestamps=0, OPcache stops checking altogether, so after you change a file the old code keeps running until the cache is cleared. In WordPress, keep the following in mind:

  • When you update plugins, themes or core from the admin, WordPress (5.5 and later) invalidates the cache of the files it copied with wp_opcache_invalidate(). This runs in the web process, so it affects the PHP-FPM cache.
  • When you update with WP-CLI (wp plugin update and so on), the invalidation runs in the CLI process and never reaches the PHP-FPM cache.
  • When you replace files with git pull, rsync, FTP and the like, the cache is not cleared automatically either.

Use validate_timestamps=0 only if your deployment process can reload PHP-FPM; otherwise it is safer to leave it at 1 and tune revalidate_freq.

Clear the cache

The simplest way to clear the PHP-FPM cache is to reload PHP-FPM.

sudo systemctl reload php8.3-fpm

Run this command at the end of a deployment or after updating with WP-CLI. As explained above, wp eval 'opcache_reset();' and php -r 'opcache_reset();' only clear the CLI cache.

On shared hosting without shell access, you would have to call opcache_reset() over the web. However, many shared hosts run with opcache.validate_timestamps=1, so replaced files are usually picked up within revalidate_freq seconds. Check the actual values in your host's control panel or with phpinfo().

Should you use JIT with WordPress?

Since PHP 8.0, OPcache includes a JIT (which compiles code to native machine code at run time). The defaults differ by PHP version.

PHP opcache.jit default opcache.jit_buffer_size default Result
8.0–8.3 tracing 0 The buffer is 0, so JIT doesn't run
8.4 and later disable 64M JIT doesn't run

Either way, JIT is not used with the defaults. JIT suits compute-heavy work, and its effect tends to be small for WordPress, which spends most of its time on database and file I/O. If you want to try it, enable it on a staging environment as shown below, measure response times, and compare before using it in production.

opcache.jit=tracing
opcache.jit_buffer_size=64M

Enabling JIT uses shared memory for jit_buffer_size on top of opcache.memory_consumption.

Related articles

Questions about WordPress? The publisher of this site is based in Japan and replies in Japanese. Contact (Japanese)

お気軽にご相談ください

お見積りへ お問い合わせへ
▲