Hosting & Servers

Properly Configuring OPcache on Hosting and Servers

If you have to restart the service after every code change or OPcache memory fills up, this guide shows the correct configuration of validate_timestamps and memory size.

Hosting & Servers

You've put the site on the server, you change the code, you refresh the page, and nothing happens. You save the file again, and still the same old output. Then you restart the PHP service once and everything works. This is exactly where you should look at OPcache, not the browser cache and not the CDN.

OPcache keeps the compiled bytecode of PHP files in shared memory so that every request doesn't have to read and parse the file from disk again. On a typical WordPress site, this single layer alone can bring script execution time from around 80 milliseconds down to 25 milliseconds. The exact number depends on the number of plugins and the size of the code, but the direction of change is always the same.

Why code changes don't take effect

The key parameter here is: opcache.validate_timestamps. When its value is 1, OPcache checks the file modification time every few seconds (based on opcache.revalidate_freq) and if the file is newer, it discards the cached version. When its value is 0, this check is completely disabled and the same old bytecode is served until PHP is restarted or the cache is cleared.

On a production server, setting it to 0 is tempting because it saves a few milliseconds. But the cost is that every deploy must be accompanied by an explicit cache-clearing step, otherwise half of the users see the old version of the site and half see the new version. If your deploy process isn't automated and reliable, keep 1 and set opcache.revalidate_freq to 2. The performance difference is negligible in practice; the difference in hassle is not.

This is where they make a mistake

The common mistake is that a developer sets validate_timestamps=0 on the development server too, then spends hours hunting for a bug that doesn't exist. The sign is this: you change the code with var_dump, the output doesn't change, but when you copy the file to a new name and call it, it works correctly. That moment means the cache, not the application logic, is the culprit. On the development environment, always set validate_timestamps=1 and revalidate_freq=0 so that every change is seen immediately.

How much OPcache memory should we set

The default value of opcache.memory_consumption in many builds is 128 megabytes, and it's not enough for a WordPress site with several plugins. When this memory fills up, OPcache starts discarding scripts and recompiling them; the result is a performance drop while you see no error in the log.

To see the actual status, run the opcache_get_status() script or start with the output of php -i | grep opcache. If opcache_get_status()['opcache_statistics']['oom_restarts'] is greater than zero, it means you've run out of memory. The number 256 is a reasonable starting point for most sites; heavy sites with large frameworks reach 512 as well.

Two other parameters are also important. opcache.max_accelerated_files is the ceiling on the number of cached files and its default is 10000. A WordPress installation with heavy plugins easily exceeds this number. Set the value to 20000 or 30000. And opcache.interned_strings_buffer, whose default is 8 megabytes; set it to 16 or 32 so that duplicate strings between files are shared.

Configuration example

opcache.enable=1
opcache.memory_consumption=256
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=20000
opcache.validate_timestamps=1
opcache.revalidate_freq=2
opcache.save_comments=1
opcache.fast_shutdown=1

Don't underestimate that save_comments=1. If you set it to 0, annotations and DocBlock comments are removed from the bytecode and anything that relies on them breaks; from annotation-based ORMs to some WordPress plugins. The memory savings are small, the cost of breakage is large.

OPcache or APCu or Redis?

These don't replace each other and confusing them wastes your time.

LayerWhat it cachesWhere it's used
OPcacheBytecode of PHP filesEverywhere, without exception
APCuApplication data in the memory of the same serverSingle-server object cache
Redis / MemcachedApplication data on a separate serviceMultiple servers, shared sessions

If the site is on a single server, APCu works more simply and faster than Redis because it has no network round-trip. If you're on multiple servers behind a load balancer, APCu is useless because each server has its own cache and the user may go to another server after each request. There, Redis is the right choice. For setting up on a single-server Linux hosting, the combination of OPcache along with APCu is almost always enough.

When you should turn off OPcache

On the development environment, as we said. Also when you use opcache.file_cache and the cache files on disk are shared between different PHP versions; this mode can return incompatible bytecode and give a strange error that has nothing to do with your code. If you see such an error, first clear opcache.file_cache.

And one practical point: after every deploy, if you have validate_timestamps=0, don't forget to clear the cache. The simplest way is to call opcache_reset() from a CLI script, or restart php-fpm with systemctl reload php8.2-fpm. Note that reload is enough and there's no need for a full restart; reload doesn't drop active connections.

If after these settings you still see slowness, the problem is elsewhere. Start by reading the server error log and see if there's a recurring error that redoes part of the work each time. And if the site sometimes goes completely down, the right path is diagnosing intermittent downtime, not touching cache settings.

Frequently asked questions

Why don't changes take effect after modifying a PHP file?

Because OPcache has kept the previous compiled version in memory and the file modification time check is disabled. Check the value of opcache.validate_timestamps; if it's 0, either set it to 1 or clear the cache with opcache_reset() after every change.

What is the appropriate value for opcache.memory_consumption?

For most WordPress sites, 256 megabytes is a good starting point. If in the output of opcache_get_status() the value of oom_restarts is greater than zero, memory is low and you should raise it. Heavy sites with large frameworks go up to 512 megabytes as well.

Is OPcache also enabled on shared hosting?

On most Linux hostings OPcache is enabled by default, but you usually can't change its values from within the panel because the settings are applied at the server level. If you need precise configuration, you should go for a server that has full control over php.ini.

What's the difference between OPcache and WordPress cache?

OPcache works at a lower level and independently of WordPress and only caches the bytecode of PHP files. WordPress cache keeps the output of queries and HTML fragments. These two aren't rivals; both should be enabled and each covers a different layer.

If right now you have access to php.ini on your server, first check the value of max_accelerated_files. This parameter affects WordPress sites more than you think and gets the least attention.

ServerNet Support

ServerNet engineering & editorial team — specialists in infrastructure, networking and web hosting.

Linux Hosting
Share:

Comments 0

No comments yet — be the first!

Leave a comment

Related service

Linux Hosting

PHP & MySQL hosting on NVMe RAID-10 with LiteSpeed — the solid base for any website, from personal blogs to enterprise Laravel apps. At a price competitors can't explain.