PHP OPcache and JIT: The Real Performance Gain and Its Limits
OPcache stores compiled code in memory so PHP skips re-parsing every file on every request, often lifting throughput two to three times. JIT is an added gain for compute-heavy work, not for web apps dominated by I/O.
OPcache is the cheapest and fastest performance win you get in PHP, and it is often already on but with settings never tuned for production. The idea is that PHP is an interpreted language: on every request it reads code files from disk, parses them as text, and compiles them into opcodes before execution, then throws all of that away at the end of the request only to redo it from scratch on the next one. OPcache breaks this cycle by compiling each file once and keeping the opcodes in shared memory, so later requests are served from a ready copy with no disk read and no re-parsing. The practical result on a typical Laravel or WordPress app is a two to three times increase in requests served per second, plus a clear drop in vCPU use because the heaviest step, compilation, no longer repeats. The direct answer: enable and tune OPcache for production first, then consider JIT only if your load is compute-bound rather than I/O-bound.
How OPcache Works and What It Actually Saves
On the first request for a file, PHP compiles it and stores the result in a shared memory area sized by opcache.memory_consumption. Later requests for the same file jump straight to execution. A modern app can load hundreds of files per request, so imagine saving thousands of re-parses per minute. That saving is what cuts response time and frees the processor to serve more requests on the same server. This directly benefits companies running custom systems on a cloud server, where every saved point of vCPU means more headroom before an upgrade is needed.
Critical Production Settings
The gap between a tuned and an untuned OPcache is large. These are the key knobs:
| Setting | Role | Typical production value |
|---|---|---|
| opcache.memory_consumption | Memory for opcodes | 128 to 256 MB |
| opcache.max_accelerated_files | Maximum files cached | 20000 for a large app |
| opcache.validate_timestamps | Whether to check file changes each request | 0 in production |
| opcache.interned_strings_buffer | Memory for deduplicating strings | 16 to 32 MB |
The most consequential knob is validate_timestamps. When it is 1, PHP checks on every request whether the file changed on disk so it can recompile, and that is a repeated disk check with no benefit in production because the code is fixed between deploys. Set it to 0 in production to remove the check entirely, but remember the cost: the server will not see any code change until you clear the OPcache or restart PHP-FPM. Make that the final step of your deploy script. As for max_accelerated_files, if it is lower than your project's real file count, files get evicted and recompiled, so set it above your application's file count.
Watch the Hit Rate
The number that tells you OPcache is working efficiently is the hit rate. In a healthy production it should exceed 99%. If you see it lower, usually memory_consumption is too small or max_accelerated_files is below your file count, so memory fills, files get evicted, then re-parsed. Also watch consumed memory and the number of cached scripts, since these indicators reveal whether you need to raise the limits.
When JIT Actually Helps
JIT, the just-in-time compiler, arrived in PHP 8, and many expected it to speed up everything, but the reality is more precise. JIT turns hot opcodes into native machine code that runs directly on the processor, so it wins on compute-heavy work: image processing, numerical math, algorithms that loop millions of times over in-memory data. A typical web app, though, does not spend its time computing, it waits: a database query, a file read, an external API call. That waiting, the I/O, JIT does not speed up at all, because it is not about code execution speed but about waiting on an external resource. So on a Laravel app dominated by the database, the JIT gain may be a few percent, while on a pure compute task it can nearly double the speed.
The practical takeaway: OPcache is a guaranteed win for every PHP app without exception, always enable it. JIT is a conditional win, test it with before and after numbers on your real load, and do not assume it will speed up an ordinary web app. If you are building genuine compute load such as AI model processing, you may benefit more from routing the work to AI hosting with ready templates than from squeezing JIT in PHP.
Before and After Numbers on a Typical App
To measure the impact, do not guess. Run a load test on a page representative of your app, once with OPcache disabled and once after tuning it for production. The recurring pattern we see: an app serving around 150 requests per second without OPcache jumps to around 400 requests per second after enabling and tuning it, with average response time roughly halved and vCPU use dropping because repeated compilation is gone. In practice this improvement means a Business server with four cores can carry double the traffic before you think about upgrading.
The Right Order of Optimization
Always start with the cheapest impact: enable and tune OPcache, since it gives the biggest gain for the least effort. Next, fix slow queries and add indexes, because most web app slowness lives in the database, not in PHP execution. Then consider caching repeated results. Finally, if genuine compute load remains after all that, test JIT and measure. Enabling JIT before tuning OPcache or fixing the database is optimizing the wrong place.
preload: a Step Beyond OPcache
PHP offers a deeper feature than ordinary OPcache called preload, which loads specific files once when PHP-FPM boots and keeps them in memory for the process lifetime, shared across all requests without any re-check. The benefit is that preloaded classes and functions are instantly ready with no loading, cutting an extra slice off boot time. But it carries an operational cost: any change to a preloaded file does not appear until you fully restart PHP-FPM, not just clear the cache. So preload suits stable libraries that do not change between deploys, not your own code that you edit daily. Treat it as an advanced optimization after you have tuned base OPcache and measured that you still pay in boot time.
An important point when measuring: make sure you test in an environment that truly resembles production. Many measure on a development machine with validate_timestamps on, then wonder at the difference in numbers. The fair environment for measurement is the exact production settings, otherwise you compare two different states and reach a misleading conclusion.
OPcache and Process Count
OPcache is memory shared across all PHP-FPM processes on the server, so its consumption does not multiply with process count, which is in your favor. But note that the memory you allocate to it is carved from the server's total memory. On a plan with limited RAM, balance what you give OPcache against what you leave for PHP processes themselves and for the database if it sits on the same server. A figure of 128 MB for OPcache is reasonable for most apps, and you raise it only if you see the hit rate drop or memory fill, not merely as a precaution.
OPcache on Managed Hosting
If your app is on managed cloud hosting with a cPanel panel rather than a server you run yourself, OPcache is usually enabled and tuned for you on our side with reasonable production settings, so you do not need to touch it. This is one meaning of managed: the base performance layers are set up in advance. But if you run your own server on a cloud server, the responsibility is yours, and the gain is large for a small effort. Know which operating model you are in before you hunt for a setting that may already be tuned, so you save your time and direct it to improving your queries, where most of the real slowness lives.
Conclusion: Practical Steps
Enable OPcache on every production server, raise memory_consumption to 128 or 256 MB and max_accelerated_files above your project's file count. Set validate_timestamps to zero in production and clear the cache at the end of every deploy. Watch the hit rate and keep it above 99%. Do not enable JIT until you have measured that it helps your compute load, and do not expect magic from it on an I/O-bound app. If you need a Saudi server with roughly 8ms response time from Riyadh to run your app efficiently, review the cloud server and pick a plan that fits your load, since upgrades are instant as you grow.


