What Is OPcache? How PHP Opcode Caching Speeds Up Your Site

What is OPcache and what does it do in PHP?
OPcache is PHP's built-in bytecode cache. It stores compiled scripts in shared memory, so PHP does not have to read, parse and compile the same files on every request. As a result, your server does less repeated work, CPU load drops and dynamic pages usually respond faster.
In this guide we explain what OPcache is, then walk through the main php.ini directives, the checks that prove it works and the reset step after a deployment. Everything rests on the official PHP manual. Our team is a digital marketing and web team, not a hosting company, so we do not claim to run servers for you.
We write for two readers. The first is a website or store owner who wants to talk to a hosting provider with confidence. The second manages a VPS or cPanel account and wants commands to run step by step. Both groups get notes below.
What is OPcache doing when PHP runs a request?
To answer what is OPcache saving you, first look at the normal path. Before PHP runs a script, it does several jobs. It reads the file from disk, splits it into tokens, parses the syntax and compiles it into opcodes. Only then does the Zend engine execute those opcodes. OPcache caches the first half of that chain, which is the compile step.
With OPcache on, the first request still compiles the file. After that, PHP writes the result to shared memory. Later requests skip parsing and compiling, and they run the stored opcodes directly. In other words, you cache the compiled code, not the page output.
Many readers who ask what is OPcache expect page caching, so this difference matters. Page caches store finished HTML, but OPcache lets PHP build each dynamic page again. It only cuts the cost of preparing the code. Therefore your database queries and outside API calls do not get faster with OPcache alone.
- Skipped: reading, parsing and compiling the file.
- Not skipped: running the code, database queries and template output.
- Stored: compiled opcodes in shared memory.
So the technical answer to what is OPcache fits in one sentence: compile once, share the result. Everything else is tuning how big that shared space is and when it refreshes.
Is OPcache enabled on your server?
The PHP manual lists opcache.enable with a default of 1, which means on. However, your host may have changed php.ini. Also, having the extension installed is not the same as having it active. For a reliable answer, check your own environment.
You have three options. First, list the loaded modules on the command line. Second, search the phpinfo output for the Zend OPcache section. Third, call opcache_get_status. That function returns false when OPcache is off and a status array when it is on.
php -m | grep -i opcache
php -i | grep -E "opcache.(enable|memory_consumption)"
Note that these commands show the CLI build. According to the manual, opcache.enable_cli defaults to 0. Therefore the CLI output may not match what your website sees. To read the web side, you need a page that runs through your web server, and we cover that below.
How does OPcache change the speed of a WordPress or WooCommerce site?
WordPress loads core files, a theme and plugins on every request. That can mean dozens or even hundreds of PHP files. For this reason, OPcache helps most on file-heavy applications like WordPress. The size of the gain depends on your plugins, hardware and traffic, so we do not promise a fixed percentage.
People who search what is OPcache for WordPress should know one thing: it already ships with PHP. Also, it does not replace a page cache plugin. A page cache serves ready-made HTML and often skips PHP entirely. OPcache lightens PHP when it does run. The two layers complement each other.
The difference is clearer on online stores. Cart, checkout and account pages usually bypass the page cache, so PHP runs every time. On those dynamic pages, OPcache does real work. For the link between speed and revenue, read our post on ecommerce page speed and sales.
Which OPcache settings matter most?
OPcache offers dozens of directives, but five or six cover most sites. The table below lists defaults from the official OPcache configuration page. The manual notes that some defaults change between versions, so always check the page for your PHP version.
| Directive | Default (php.net) | What it does |
|---|---|---|
| opcache.enable | 1 | Turns the opcode cache on. |
| opcache.enable_cli | 0 | Turns it on for the CLI build. |
| opcache.memory_consumption | 128 (MB) | Sets the shared memory size. |
| opcache.interned_strings_buffer | 8 (MB) | Sets memory for deduplicated strings. |
| opcache.max_accelerated_files | 10000 | Sets the maximum number of script keys. |
| opcache.validate_timestamps | 1 | Checks files for changes by timestamp. |
| opcache.revalidate_freq | 2 (seconds) | Sets how often that check runs. |
| opcache.save_comments | 1 | Keeps doc comments in the cache. |
Most of these directives only change at php.ini level. The manual marks memory_consumption, max_accelerated_files and enable_cli as INI_SYSTEM. So you cannot change them from a script with ini_set.
How do you choose opcache.memory_consumption?
This directive sets how much shared memory OPcache may use, in megabytes. The manual gives a default of 128 MB and enforces a minimum of 8 MB. In addition, the interned strings buffer comes out of this total. So the 8 MB string buffer is a slice of the 128 MB.
You do not guess the right value. You measure it. Run the site under normal traffic for a while, then read used_memory, free_memory and wasted_memory in the opcache_get_status output. If free memory stays near zero, or cache_full reads true, raise the value.
On the other hand, an oversized value wastes RAM. On a small VPS, every megabyte matters for other services too. Therefore raise the number in small steps and check the status output after each change.
- First, measure current usage.
- Then raise the value by a reasonable step.
- Finally, restart PHP and read the status again.
Why does opcache.max_accelerated_files matter, and how do you size it?
This directive caps the number of script keys in the cache hash table. The default is 10000. According to the manual, the real value is the first prime from the set 223, 463, 983, 1979, 3907, 7963, 16229, 32531, 65407, 130987, 262237, 524521 and 1048793 that is greater than or equal to your setting.
Example calculation: suppose your site has about 12000 PHP files, including plugins and the vendor folder. By the manual's prime list, the default 10000 rounds up to 16229, so 12000 files fit. With 20000 files, the value would round up to 32531. These numbers are examples only, so count your own files.
To count them, run a simple command in your project folder.
find /var/www/example.com -name "*.php" | wc -l
Keep in mind that the count covers every script that enters the cache, not only the busy ones. If you hit the limit, new files stay out of the cache, and the compile cost returns on some requests. The manual lists a valid range of 200 to 1,000,000.
Should opcache.validate_timestamps be on or off?
This is the most important trade-off in OPcache. When it is on, OPcache checks every revalidate_freq seconds whether a file changed. When it is off, it never checks. The manual says that with it off, you must call opcache_reset, call opcache_invalidate or restart the web server for file changes to show.
| Setting | Benefit | Watch out for |
|---|---|---|
| validate_timestamps=1 | Your edits show up within seconds. | Each check adds a small file system cost. |
| validate_timestamps=0 | PHP skips file system checks. | You must reset the cache after every deployment. |
Which one should you choose? Keep it on in development, because you do not want to think about resets after each edit. On a live site, turning it off looks tempting for speed. However, only do it when your deployment process resets the cache automatically.
The risk is sharper on WordPress. If you update a plugin or theme from the dashboard, files change on disk. With the setting off, old code can stay in memory, and the site can behave as if it updated halfway. Therefore do not turn it off on a live site that you do not fully control.
What do revalidate_freq, save_comments and the interned strings buffer do?
With validate_timestamps on, revalidate_freq sets the check interval in seconds. The default is 2. According to the manual, a value of 0 means OPcache checks for updates on every request. If validate_timestamps is off, PHP ignores this directive.
The save_comments directive defaults to 1. If you turn it off, OPcache drops doc comments and the cache shrinks a little. However, the manual warns that frameworks which read annotations from comments can break, including Doctrine, Zend Framework 2 and PHPUnit. So leave it alone unless you know what your code depends on.
The interned strings buffer keeps one copy of repeated strings. The default is 8 MB. On a large codebase, this area can fill up, and you would see it in the status output. In that case, consider raising it, but measure first.
- revalidate_freq: check interval, only relevant when timestamp checks are on.
- save_comments: keeps comments, which annotation based code needs.
- interned_strings_buffer: string area, taken from the total memory.
What does a sample OPcache configuration look like?
The block below is an example, not an official recommendation and not a default. Adjust the numbers to your own measurements. If your host does not let you edit php.ini, ask for these values through the control panel's PHP options or through support.
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
We left validate_timestamps on on purpose. Turning it off assumes your deployment includes a reset step. Also, the location of the config file varies by distribution and setup. To find the right file, look at the Loaded Configuration File line in the phpinfo output.
After a change, PHP has to read the settings again. INI_SYSTEM directives do not change at runtime. Therefore you restart or reload the PHP FPM or web server process, and the service name differs between setups.
How do you confirm the settings work with phpinfo and opcache_get_status?
Writing a setting is not enough, because you must see it apply on the web side. The simplest way is a temporary PHP file that calls phpinfo. Look for the Zend OPcache section and compare your values with it. Delete the file as soon as you finish, since phpinfo exposes server details.
For more detail, use opcache_get_status. If you pass false as the include_scripts parameter, the long script list drops out of the output, and the result is easier to read. This single line is enough for the file body, and you add the PHP opening tag yourself.
var_dump(opcache_get_status(false));
Look at four groups of fields. The opcache_enabled and cache_full fields show the overall state. Next, the memory_usage section shows used, free and wasted memory. Then opcache_statistics holds num_cached_scripts, hits, misses and opcache_hit_rate. Finally, oom_restarts and hash_restarts separate the reasons for restarts.
How do you reset OPcache after a deployment?
When you ship new code, old opcodes can stay in memory. With validate_timestamps on, this fixes itself within seconds. With it off, you must reset the cache yourself. PHP gives you two functions: opcache_reset clears the whole cache, while opcache_invalidate invalidates one file.
| Method | Scope | Note |
|---|---|---|
| opcache_reset() | Whole cache | Clears the memory cache only, not the file cache. |
| opcache_invalidate(file) | One file | Call it before you delete the file. |
| Restart the PHP service | Whole cache | The process starts fresh, with a short risk of downtime. |
The manual adds two notes on opcache_invalidate. By default, it only invalidates the file if the modification time is newer than the cached opcodes, and the force parameter makes it unconditional. In addition, it forces a recompile but does not remove the entry. So it cannot replace opcache_reset when the cache is full.
Why does OPcache behave differently for CLI and web?
On most setups, command line PHP and the PHP behind your web server or FPM are separate processes with separate opcode caches. User notes in the PHP manual say it plainly: running opcache_reset from the CLI does not clear the web cache. The function may return true, yet the web side stays unchanged.
Anyone asking what is OPcache for the CLI should know this detail, because it causes many mistakes. Someone connects over SSH, runs a reset command and assumes the problem is gone. Meanwhile the website keeps serving old code. Therefore make sure you run the reset on the web side.
Also, enable_cli defaults to off. So seeing OPcache off in the CLI is not a problem by itself. What matters is the setting your web requests see. For that reason, always verify through an HTTP request.
- CLI output may not show the web state.
- A reset from the CLI may not touch the web cache.
- A script that runs through the web server gives the reliable check.
How do you use an OPcache reset URL safely?
User notes in the manual suggest a common trick: write a small web-accessible script and call it. Technically it works. However, if you leave that script open to everyone, anyone can empty your cache again and again, and slow your site for no reason.
So follow two rules. First, never leave the script without authentication, and allow only the server's own address. Second, do not place it on a guessable path. Better still, do not keep it at all, and run the reset as a step in your deployment tool.
Leaving a temporary script with a token or password in the document root is risky too. A forgotten file can stay open for months. To widen your security view, our guide to OWASP Top 10 web security vulnerabilities is a good start.
If you cannot build a safe setup yourself, ask your hosting provider or your development team to handle the post-deployment reset.
What happens when OPcache fills up?
When OPcache is full, it cannot cache new scripts. The manual's status array includes a cache_full field and an oom_restarts counter. The oom_restarts counter shows restarts caused by running out of memory. Meanwhile, hash_restarts counts restarts tied to a full key table.
The symptoms are usually indirect. Server CPU use can stay higher than expected, and some pages can open slowly now and then. Also, opcache_hit_rate looks low. However, other causes can produce the same signs, so read the status output for a firm diagnosis.
- If cache_full is true, memory or the file limit is full.
- When oom_restarts keeps rising, memory_consumption is too small.
- Rising hash_restarts means you should review max_accelerated_files.
- A low hit rate can mean the cache never warmed up or resets too often.
The fix is usually to raise the relevant directive and restart the service. Still, confirm first that the problem really comes from OPcache.
What is OPcache JIT, and do you need to turn it on?
JIT is a compiler inside OPcache that turns opcodes into machine code. According to the PHP manual, the default of opcache.jit became "disable" in PHP 8.4.0, while earlier versions defaulted to "tracing". If jit_buffer_size is zero, JIT stays off anyway. Check the manual for your own version.
A typical WordPress or store site waits mostly on the database and on input and output, so do not expect a big gain from JIT. JIT matters more for heavy computation. For this reason, get the ordinary OPcache settings right first.
In addition, the manual says that when JIT is on, the shared memory segment equals memory_consumption plus jit_buffer_size. So it changes your memory plan. Turn JIT on only after you measure your own workload, and record the result.
How do OPcache, Redis, Memcached, Varnish and page caches differ?
People often ask what is OPcache compared with other caches, because they mix these tools up and call all of them a cache. In fact each one works at a different link of the chain. OPcache stores code, Redis and Memcached store data, and Varnish or a page cache stores HTTP output. Therefore none of them replaces another, and they complement each other.
| Layer | What it stores | Where it runs |
|---|---|---|
| OPcache | Compiled PHP code | In PHP shared memory |
| Redis or Memcached | Objects and query results | In a separate memory service |
| Varnish or a full page cache | Ready HTML responses | In front of the web server or inside the app |
We already cover data caching in detail in how caching works with Redis and Memcached, so we do not repeat it here. Just remember this: hosts usually install OPcache already, while the others need separate decisions.
How do you measure the effect of OPcache?
Changing settings without measuring is guesswork. Before you touch OPcache, test the same pages under the same conditions, then test again afterward. The most useful metric is how quickly the server sends the first byte. You can read it in browser developer tools or in a Lighthouse report.
Do not run a test only once. Network and server load vary, so repeat each measurement several times. Also, the first request before the cache warms up is always slower. For that reason, compare results with a warm cache.
We explain Lighthouse in our Lighthouse performance test guide. For the link between speed and search visibility, see how site speed affects SEO. For example, you can find LCP and INP in our Core Web Vitals guide.
We do not promise a number. The result depends on your codebase, plugins and server.
How does OPcache show when a code change goes live?
The answer depends on two directives. If validate_timestamps is on, OPcache checks the file's modification time every revalidate_freq seconds. The default is 2 seconds. Therefore a new version goes live shortly after you change a file.
If validate_timestamps is off, the picture changes. OPcache never looks at the file, and it serves the old opcodes until you tell it otherwise. The manual also says to call opcache_invalidate before you delete a file. Otherwise the entry can linger in the cache.
In practice, you ship a fix, but visitors still see the old behavior. First, rule out the cache layers in order. Check the browser, then the page cache, then OPcache. This way you find the guilty layer quickly.
What can you ask your hosting provider about OPcache?
If you do not manage the server, a good question is half the fix. Support teams often give generic answers. If you ask concrete and measurable questions, the provider solves the issue faster, and you learn what changed.
- Is OPcache on for the web side of this account?
- What are the memory_consumption and max_accelerated_files values?
- Is validate_timestamps on, and if not, how do you reset after a deployment?
- Can I change these values from the panel or through a support ticket?
- Does a PHP service restart cause a short outage?
Write down the answers and keep a record. Later, if a problem appears after an update, knowing which setting changed and when makes your work easier. Then verify your own values with the measuring steps in this guide.
When should you leave OPcache to your hosting provider?
On shared hosting, your control over php.ini is limited, and that is normal. The provider most likely manages OPcache with one configuration for all accounts. In that setup, asking support a concrete question works better than chasing settings.
Leave the work to the provider or to someone who knows infrastructure in these cases. If several sites share one server, a single wrong value affects all of them. Experimenting on a live store is risky too. Also, if you do not know whether a service restart causes downtime, do not touch it.
- Without access, ask support for the current values and the reset method.
- On a live store, try the change on a test copy first.
- Never touch server settings without a backup.
For a backup plan, read our website backup strategy guide. For the hosting choice itself, how to choose web hosting walks you through it.
What are the most common OPcache mistakes?
Most mistakes come not from the setting itself but from checking it in the wrong place. The list below gathers the confusions we see most often in the documentation. All of them follow from behavior in the official docs, not from our own server experience.
- Reading CLI output to guess the web state.
- Turning off validate_timestamps and forgetting the reset after a deployment.
- Leaving the reset script open to everyone.
- Picking max_accelerated_files without counting your files.
- Turning off save_comments and breaking annotation based code.
- Forgetting to restart the service after a change.
Another mistake is treating OPcache as the cure for all slowness. A slow database query or heavy images will not improve with OPcache. So find the bottleneck first. To see what your site runs on from the outside, try our website technology checker.
What should you do next after you tune OPcache?
Once OPcache is set up well, the other layers come next. Measure first, then pick the biggest bottleneck. On most sites, that means images, heavy scripts or theme and plugin bloat. Server settings are only one part of the picture.
To see how speed connects to search results, review the SEO side too. If you want technical health and a content plan handled together, our SEO consulting covers it. For a new site where you want speed targets from day one, see our web design service.
We are not a hosting company, and we do not promise to run servers. Still, as a web and marketing team, we help you understand how a hosting decision affects performance and security. In short, try the steps in this guide yourself, and ask your provider or us where you feel unsure.



