PHP Preloading (opcache.preload)
debt(d5/e3/b3/t7)
Closest to 'specialist tool catches' (d5), opcache-gui and blackfire (per detection_hints) can show opcache miss rates and whether preload is configured, but issues like stale preloaded code after deploy are silent until observed.
Closest to 'simple parameterised fix' (e3), quick_fix is creating a preload.php and setting two ini directives — small config change in one component, not a one-liner but contained.
Closest to 'localised tax' (b3), applies only to web context and FPM deployment configuration; impacts deploy process (must restart FPM) but doesn't reshape application code.
Closest to 'serious trap' (t7), misconception explicitly states devs assume preloading always helps and that changes are picked up — but stale code runs until FPM restart, contradicting normal PHP deploy expectations where file changes are picked up immediately.
Also Known As
TL;DR
Explanation
PHP 7.4 introduced preloading via opcache.preload — a php.ini directive pointing to a bootstrap script that calls opcache_compile_file() on framework and application files. At PHP-FPM startup these files are compiled to bytecode and mapped into shared memory, available to all worker processes with no per-request file stat or compilation cost. Frameworks like Symfony and Laravel ship preload scripts. Gains are most noticeable for large frameworks (5–10% throughput). Caveat: preloaded files cannot be updated without restarting PHP-FPM; always disable preloading in development environments.
Diagram
flowchart TD
subgraph Without_Preload
REQ_A[Request 1] --> OPCACHE2[OPcache loads class files<br/>on first use per worker]
REQ_B[Request 2] --> OPCACHE3[Same class loaded again<br/>in each worker process]
end
subgraph With_Preload
BOOT[PHP-FPM boots] --> PRELOAD2[opcache.preload runs<br/>loads framework classes once]
PRELOAD2 --> SHARED[Shared memory<br/>available to ALL workers instantly]
SHARED --> FAST2[Zero class loading overhead<br/>on any request]
end
style PRELOAD2 fill:#1f6feb,color:#fff
style SHARED fill:#6e40c9,color:#fff
style FAST2 fill:#238636,color:#fff
Common Misconception
Why It Matters
Common Mistakes
- Preloading files that change frequently — FPM must restart for changes to take effect.
- Not setting opcache.preload_user — FPM won't preload as root by default.
- Preloading the entire vendor directory — classes that are rarely used waste shared memory.
- Not measuring the impact — preloading adds startup time and memory; benchmark before committing.
Code Examples
; php.ini — preloading not configured:
; opcache.preload = ; Not set — no preloading
; opcache.preload_user = ; Required — must be non-root
; Correct:
opcache.preload = /var/www/app/preload.php
opcache.preload_user = www-data
; php.ini — preload at FPM startup (PHP 7.4+)
opcache.preload = /var/www/app/preload.php
opcache.preload_user = www-data
// preload.php — compile key files on startup:
<?php
foreach (glob('/var/www/app/src/**/*.php') as $file) {
opcache_compile_file($file);
}
; Laravel: php artisan optimize
; Symfony: php bin/console cache:warmup
; Verify:
$ php -r "print_r(opcache_get_status()['scripts']);"
; Biggest win: eliminates per-request parsing of framework files