PHP OPcache is one of the easiest performance wins you can get for WordPress, Laravel and WooCommerce, yet on many servers it is either misconfigured or barely used. When we tune new environments at dchost.com, OPcache is always in the first batch of settings we review – right after PHP-FPM and basic PHP limits. A few lines in php.ini can cut CPU usage dramatically, lower TTFB and make heavy dashboards feel much more responsive. In this guide we will walk through practical OPcache settings that work well in real WordPress, Laravel and WooCommerce projects, explain what each directive does in plain language, and share configuration examples you can paste into your own server (and then fine‑tune). Whether you are on shared hosting, an NVMe VPS or a dedicated server, you will leave with a clear template for safe, fast OPcache configuration that plays nicely with your deployment workflow.
İçindekiler
- 1 What PHP OPcache Really Does for Your PHP Apps
- 2 OPcache Must‑Have Settings: The Short Version
- 3 Understanding Key OPcache Directives One by One
- 3.1 opcache.enable and opcache.enable_cli
- 3.2 opcache.memory_consumption
- 3.3 opcache.interned_strings_buffer
- 3.4 opcache.max_accelerated_files
- 3.5 validate_timestamps and revalidate_freq
- 3.6 opcache.max_wasted_percentage
- 3.7 opcache.save_comments
- 3.8 opcache.file_update_protection
- 3.9 opcache.restrict_api
- 3.10 JIT: opcache.jit and opcache.jit_buffer_size
- 4 Recommended OPcache Configurations by Stack
- 5 How OPcache Interacts with PHP‑FPM, JIT and Application Caches
- 6 Monitoring and Debugging OPcache in Production
- 7 Safe Deployment Workflow with OPcache Enabled
- 8 Putting It All Together: Practical Checklists
- 9 Final Thoughts and Next Steps
What PHP OPcache Really Does for Your PHP Apps
Every time PHP executes a file, it first needs to read the source code, parse it and compile it into opcode (machine‑readable instructions). Without OPcache, this happens on every request. OPcache stores the compiled opcode in memory so the next request can reuse it instantly instead of recompiling. That means:
- Less CPU time spent compiling PHP files
- Lower request latency, especially under load
- More capacity from the same hardware
For WordPress and WooCommerce, this mostly accelerates core, plugin and theme PHP files. For Laravel, it speeds up framework classes, your application code and vendor libraries. OPcache is not a replacement for object cache (Redis/Memcached) or full‑page caching, but it is the base layer. In fact, it works best when combined with the techniques we covered in our server‑side optimization guide for WordPress (PHP‑FPM, OPcache, Redis and MySQL tuning).
OPcache Must‑Have Settings: The Short Version
Before diving deep, here is a practical baseline we frequently use on PHP 8.x for WordPress, WooCommerce and Laravel on a typical VPS (2–4 vCPU, 4–8 GB RAM):
; Enable OPcache
opcache.enable=1
opcache.enable_cli=0
; Memory and file capacity
opcache.memory_consumption=256
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=20000
opcache.max_wasted_percentage=5
; File change detection (for shared hosting / simple setups)
opcache.validate_timestamps=1
opcache.revalidate_freq=60
; Safer behavior
opcache.save_comments=1
opcache.fast_shutdown=1
opcache.enable_file_override=1
; JIT (optional, usually OFF for classic WordPress/WooCommerce)
opcache.jit=0
opcache.jit_buffer_size=0
You will tune these numbers depending on:
- PHP version (7.4 vs 8.1 vs 8.2+)
- Project size (number of PHP files, plugins, Composer packages)
- Server RAM
- Deployment workflow (manual FTP vs automated CI/CD)
Next, we will go directive by directive and then build tailored configs for WordPress, Laravel and WooCommerce.
Understanding Key OPcache Directives One by One
opcache.enable and opcache.enable_cli
opcache.enable turns OPcache on for web SAPI (PHP‑FPM, mod_php, etc.). This should almost always be 1 on production servers.
opcache.enable_cli controls OPcache for the PHP CLI (command line). You may want OPcache disabled for CLI on small servers to avoid extra memory usage, but there are also good reasons to keep it enabled for Laravel artisan commands or long‑running CLI tools.
- Shared hosting / small VPS:
opcache.enable_cli=0 - Large Laravel projects with heavy CLI usage: consider
opcache.enable_cli=1
opcache.memory_consumption
This sets how much shared memory (in MB) OPcache can use to store compiled PHP code. If this is too low, OPcache fills up quickly, starts evicting old scripts and you lose most of the benefit.
- Small WordPress sites (few plugins): 64–128 MB
- WooCommerce / multiple plugins: 192–256 MB
- Medium Laravel apps with many Composer deps: 256–512 MB
- Very large multi‑tenant or monorepo apps: 512 MB+
On a server with 4–8 GB RAM, allocating 256 MB to OPcache is usually a safe starting point. Watch usage over time and increase if fragmentation grows or hit rate falls.
opcache.interned_strings_buffer
PHP can “intern” strings – store a single copy in memory and reuse it – which reduces memory usage and speeds comparisons. opcache.interned_strings_buffer controls how many megabytes are available for those interned strings.
- Default is often too low (e.g. 8 MB).
- For modern frameworks and plugin‑heavy WordPress, 16–32 MB is a better target.
We commonly use:
opcache.interned_strings_buffer=16
and go up to 32 MB on large Laravel microservice clusters with many shared libraries.
opcache.max_accelerated_files
This is the maximum number of PHP scripts that OPcache can keep track of. Each file stored in OPcache occupies a slot. If the limit is lower than the number of distinct PHP files your app uses, older entries will get dropped frequently.
Rules of thumb:
- Small WordPress sites: 8000–10000
- WooCommerce + many plugins: 20000
- Medium–large Laravel apps: 20000–40000
On modern hardware, setting this higher (e.g. 20000) is usually safe and cheap in terms of memory.
validate_timestamps and revalidate_freq
These two settings control how OPcache notices file changes:
- opcache.validate_timestamps – if 1, PHP checks file modification times periodically; if 0, it never checks (until restart or manual reset).
- opcache.revalidate_freq – how often (in seconds) it checks timestamps.
On shared hosting or any environment where files can change at random times (manual FTP, plugin uploads via dashboard), you should keep validate_timestamps=1.
Recommended patterns:
- Shared hosting WordPress:
opcache.validate_timestamps=1,opcache.revalidate_freq=60 - VPS with simple manual deploys:
revalidate_freq=30–60 - CI/CD with atomic releases: you can set
validate_timestamps=0and callopcache_reset()or reload PHP‑FPM on each deploy for maximum performance.
If you are moving towards zero‑downtime deployments, the patterns in our guides on zero‑downtime CI/CD to a VPS with rsync + symlinks and deploying Laravel on a VPS with truly zero‑downtime releases fit nicely with validate_timestamps=0.
opcache.max_wasted_percentage
OPcache memory can become fragmented over time as scripts are added and removed. opcache.max_wasted_percentage sets the threshold at which OPcache will restart itself to defragment memory.
A value of 5–10 is common:
opcache.max_wasted_percentage=5
Lower values keep fragmentation under tighter control but may trigger more frequent restarts. For most real‑world WordPress and Laravel apps, 5% is a good balance.
opcache.save_comments
Some frameworks and tools rely on PHP doc comments (for annotations, attributes discovery, etc.). opcache.save_comments chooses whether OPcache keeps these comments.
- 1 (recommended): keep comments, full compatibility
- 0: slightly less memory usage, but can break frameworks or tools that inspect docblocks
Because WordPress plugins and Laravel packages may rely on annotations, we strongly recommend:
opcache.save_comments=1
opcache.file_update_protection
This setting adds a delay (seconds) to avoid caching files that are actively being written (useful with slow NFS or network filesystems). On typical local SSD/NVMe hosting, you can keep it small or even 0.
- Local disks (typical VPS / dedicated):
opcache.file_update_protection=0 - Remote filesystems: keep default (2) or increase slightly if you see corrupted caches on deploy
opcache.restrict_api
This optional setting lets you restrict OPcache API functions (opcache_reset, opcache_invalidate, etc.) to scripts in a specific directory. It is useful if you want a deployment script to control OPcache but do not want arbitrary PHP code calling these functions.
Example:
opcache.restrict_api="/var/www/deploy-scripts"
JIT: opcache.jit and opcache.jit_buffer_size
PHP 8 introduced JIT (Just‑In‑Time compilation) as part of OPcache. JIT can speed up CPU‑heavy numeric or algorithmic workloads, but for typical WordPress and WooCommerce sites it often brings little benefit and sometimes complicates debugging.
- Classic WordPress / WooCommerce: safe to keep JIT disabled:
opcache.jit=0
opcache.jit_buffer_size=0
- Laravel APIs with heavy CPU work (image processing, complex calculations): JIT might help, but test carefully with benchmarks and monitoring before turning it on across the board.
If you plan a broader PHP 8.x tuning project, our article on the PHP 8.x upgrade checklist (OPcache preload and FPM pool tuning) gives a wider context.
Recommended OPcache Configurations by Stack
On shared hosting, you usually cannot edit the global php.ini, but you might control per‑user overrides through .user.ini or a control panel. You also have less RAM, and many users share the same PHP instance.
In this environment, keep OPcache conservative and compatibility‑focused:
; Enable OPcache for web only
opcache.enable=1
opcache.enable_cli=0
; Modest memory for many small sites
opcache.memory_consumption=128
opcache.interned_strings_buffer=8
opcache.max_accelerated_files=10000
opcache.max_wasted_percentage=10
; Always check for file changes periodically
opcache.validate_timestamps=1
opcache.revalidate_freq=60
opcache.file_update_protection=2
; Safer defaults
opcache.save_comments=1
opcache.fast_shutdown=1
opcache.enable_file_override=1
; JIT off
opcache.jit=0
opcache.jit_buffer_size=0
You will not have full control over all values on most shared plans, but understanding these directives helps you read the hosting provider’s defaults and decide when it is time to move resource‑hungry stores to a VPS. If you frequently hit “Resource Limit Reached” or see high TTFB during campaigns, combine OPcache tuning with the strategies in our guide on moving from shared hosting to a VPS without downtime.
2) WordPress & WooCommerce on a VPS or Dedicated Server
Once you control your own PHP‑FPM pools and php.ini, you can allocate more memory to OPcache and tighten timestamp checks. For a typical 2–4 vCPU, 4–8 GB RAM NVMe VPS hosting a few WordPress and WooCommerce sites, we often start with:
opcache.enable=1
opcache.enable_cli=0
; More generous memory
opcache.memory_consumption=256
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=20000
opcache.max_wasted_percentage=5
; File change detection
; If you deploy via git/rsync and control releases, you can reduce checks
opcache.validate_timestamps=1
opcache.revalidate_freq=30
opcache.file_update_protection=0
opcache.save_comments=1
opcache.fast_shutdown=1
opcache.enable_file_override=1
; JIT disabled for typical WooCommerce
opcache.jit=0
opcache.jit_buffer_size=0
On multi‑tenant VPS setups where each site has its own PHP‑FPM pool (as we often design for agencies), make sure OPcache memory per pool plus PHP memory_limit and FPM settings still fit into total RAM. Our post on PHP‑FPM settings for WordPress and WooCommerce (pm and max_children calculation) is a good companion when you size everything together.
3) Laravel on a VPS or Dedicated Server
Laravel applications tend to have more PHP files (framework + vendor + app code), so we usually raise max_accelerated_files and consider a slightly larger memory_consumption.
opcache.enable=1
; Decide per project whether CLI caching is useful
opcache.enable_cli=0
opcache.memory_consumption=256 ; or 512 for large apps
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=40000
opcache.max_wasted_percentage=5
; With proper deploys, you can disable timestamp validation
opcache.validate_timestamps=0
opcache.revalidate_freq=0
opcache.file_update_protection=0
opcache.save_comments=1
opcache.fast_shutdown=1
opcache.enable_file_override=1
; JIT off unless you tested and measured benefits
opcache.jit=0
opcache.jit_buffer_size=0
With validate_timestamps=0, you must integrate an OPcache reset into your deployment pipeline. Typical patterns:
- Reload PHP‑FPM:
systemctl reload php-fpm(or pool‑specific reload) - Call a small, protected script that runs
opcache_reset()after a new release is symlinked
This aligns nicely with the production tune‑up we describe in our Laravel production optimization guide (PHP‑FPM pools, OPcache, Octane, queues and Redis).
How OPcache Interacts with PHP‑FPM, JIT and Application Caches
OPcache and PHP‑FPM Pools
On most Linux servers, OPcache runs in shared memory per PHP‑FPM master process. Each pool shares the same OPcache instance by default. That means:
- Raising
opcache.memory_consumptionincreases shared memory for all pools - Reloading PHP‑FPM clears OPcache (all scripts are recompiled on first use)
When designing multi‑tenant hosting (many sites, one server), combine OPcache sizing with PHP‑FPM limits and PHP memory_limit. If a WooCommerce site uses 512 MB of PHP memory per request and you allow many FPM children, OPcache memory becomes relatively small in that picture. The balance across OPcache, memory_limit and process counts is often more impactful than any single directive.
OPcache vs Object Cache (Redis/Memcached)
OPcache stores compiled PHP code. Object caches store application data (e.g. query results, options, session data). Both are important but solve different problems.
- OPcache reduces CPU time spent parsing and compiling PHP
- Object cache reduces database queries and expensive computations
For serious WooCommerce or Laravel apps, you usually want both. To understand the data‑side caching piece better, you can read our guide on choosing PHP session and cache storage (files vs Redis vs Memcached) and our detailed WordPress object cache setup with Redis or Memcached.
OPcache and JIT in Real Projects
For 90% of WordPress and WooCommerce sites we see, JIT is not the bottleneck: disk I/O, database performance, slow plugins and network latency come first. JIT also adds moving parts for debugging and memory usage. In most e‑commerce and content sites, we prefer:
opcache.jit=0
opcache.jit_buffer_size=0
For compute‑heavy Laravel workloads, test JIT in a staging environment with realistic load tests (for example, using the techniques described in our article about load testing hosting with k6, JMeter and Locust). If you see a clear, reproducible gain and stable behavior, you can enable it selectively.
Monitoring and Debugging OPcache in Production
Checking OPcache Status from CLI
Start by confirming that OPcache is actually enabled and using the settings you expect. On the server:
php -i | grep -i opcache
or create a small script:
<?php
print_r(opcache_get_status());
Useful fields to watch:
- memory_usage – how much of OPcache memory is used/free
- interned_strings_usage – interned string memory usage
- opcache_statistics – hit rate, number of cached scripts, misses
Ideal situation: high hit rate (> 99%), low fragmentation, and plenty of free memory headroom. If you see OPcache memory constantly full, raise memory_consumption and/or max_accelerated_files (if RAM allows).
Common OPcache‑Related Issues
- Code changes not visible: On servers with
validate_timestamps=0, you must reload PHP‑FPM or callopcache_reset()after deploys. - Random old code after a failed deploy: If your deploy partially uploads files and OPcache caches them mid‑upload, you can end up with mixed versions. Use atomic deploys (symlink switch) and set
file_update_protection=0on local storage. - High CPU spikes despite OPcache: Often due to database problems, missing object cache, or poor PHP‑FPM tuning rather than OPcache itself. Combine OPcache tuning with broader server optimization.
Small OPcache Status Dashboard
For teams that prefer a visual overview, you can adapt a small, password‑protected dashboard page that calls opcache_get_status() and renders key metrics. Just make sure it is not publicly accessible, as it can leak path and environment information.
Safe Deployment Workflow with OPcache Enabled
Misaligned deployment and OPcache settings are a common source of “it works on some requests but not others” problems. A robust workflow usually follows these principles:
- Build/compile assets elsewhere (CI, local) so production only receives ready‑to‑run PHP and static files.
- Deploy to a new release directory, e.g.
/var/www/myapp/releases/2025-01-01-120000. - Update a symlink, e.g.
/var/www/myapp/current→ new release, atomically. - Reload PHP‑FPM or call
opcache_reset()after the symlink switch.
With this approach, you can safely run with validate_timestamps=0 and minimize filesystem checks on each request. It also integrates nicely with zero‑downtime techniques like phased FPM reloads and canary deployments. We use a similar pattern in our guides on zero‑downtime CI/CD to a VPS and Laravel deployments with Nginx, PHP‑FPM and Horizon.
Putting It All Together: Practical Checklists
Checklist for WordPress / WooCommerce
- Ensure
opcache.enable=1on all PHP‑FPM pools used by your sites - Set
memory_consumptionto at least 128 MB (256 MB for larger stores) - Set
max_accelerated_filesto at least 10000 (20000 for WooCommerce + many plugins) - Keep
save_comments=1to avoid breaking plugins relying on annotations - On shared hosting:
validate_timestamps=1,revalidate_freq=60 - On VPS/dedicated with controlled deploys: consider
validate_timestamps=0+ explicitopcache_reset()on release - Keep JIT off unless you have a clear, tested reason to enable it
Checklist for Laravel
- Raise
max_accelerated_files(20000–40000) to fit framework + vendor + app files - Start with 256–512 MB
memory_consumptionon mid‑sized apps - Disable timestamp validation and rely on atomic deploy +
opcache_reset()when you have CI/CD in place - Keep
save_comments=1for annotation‑heavy packages - Evaluate whether
enable_clineeds to be 1 for heavyartisanworkflows - Benchmark JIT only for CPU‑bound tasks; leave it off for standard CRUD APIs
Final Thoughts and Next Steps
OPcache is one of those settings that quietly pays off every single day once it is correctly tuned. For WordPress, WooCommerce and Laravel, the right configuration can shave precious milliseconds from each request, reduce CPU load during peak campaigns and give you more breathing room before you need to scale up hardware. The key is to treat OPcache as part of a broader stack: aligned with PHP‑FPM pools, PHP memory limits, database tuning and, when needed, Redis or Memcached caches.
At dchost.com we apply these OPcache patterns across our shared hosting, NVMe VPS, dedicated server and colocation setups, adapting values to each project’s size and traffic profile. If you are unsure where your current bottleneck is – OPcache, PHP‑FPM, MySQL, or storage – you can always start by measuring, then adjust one layer at a time. Use the baselines in this guide, watch OPcache stats under real traffic, and refine. And if you prefer to focus on your code while we handle the low‑level tuning, our team is ready to help you design a hosting architecture where OPcache, PHP‑FPM and your applications work together smoothly.
