In PHP, what does opcache.preload do, and what do you give up when you preload an application's classes?
answer
- a script run once at server start
- classes available with no autoloading
- constants are not preloaded
- changes need a PHP process restart
- opcache.preload_user when running as root
basics
~20 sopcache.preload runs a script once at server start; the classes, functions, interfaces and traits it loads stay in shared memory and exist in every request without autoloading. The price: changes need a server restart, and the memory is always held.
solid answer
~40 s`opcache.preload=/app/preload.php` runs that script once at server start-up, before any request. Every function, class, interface and trait it loads — by `require` or `opcache_compile_file()` — is compiled, linked and kept in OPcache's shared memory, so each request finds those symbols already defined and skips autoloading and linking them. Constants are not preloaded. The trade-offs: preloaded code changes **only when the PHP process restarts** (a reset does not reload it), it takes memory whether or not a request uses it, a later `include` of a preloaded file runs but does not redefine its symbols, and it is unsupported on Windows. A server that starts as root must set `opcache.preload_user`, otherwise startup fails. The gain is real but modest and application-specific, so I measure before and after, and usually preload a hot core rather than everything.
code
php · 13 lines<?php
// /srv/app/preload.php, run once when PHP-FPM starts
declare(strict_types=1);
$files = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator(__DIR__ . '/src/Kernel', FilesystemIterator::SKIP_DOTS)
);
foreach ($files as $file) {
if ($file->getExtension() === 'php') {
opcache_compile_file($file->getPathname()); // compile, do not execute
}
}go deeper
Know that opcache.preload runs a script at server start so its classes exist in every request without autoloading.
Explain how the preload script loads files, the difference between require and opcache_compile_file(), and why constants are left out.
Weigh the gain against restart-only updates and permanent memory, preload a hot core, and build the restart into deploys that change it.
Decide whether preloading's operational constraints fit the fleet's deploy model, and require benchmarks on real traffic before adopting it.
## What preloading is **Preloading**, available since PHP 7.4, lets a PHP server load code once at startup and keep it for its whole lifetime. You point `opcache.preload` at a PHP script: ```ini opcache.preload=/srv/app/preload.php opcache.preload_user=www-data ``` When the server starts — a PHP-FPM master, for example — it runs that script once. Every **function, class, interface and trait** defined by the files it loads is compiled, **linked** (parents, interfaces and traits resolved) and stored permanently in OPcache's shared memory. From then on, each request starts with those symbols already declared: no autoloader call, no file lookup, no linking. ## How the preload script loads code The manual describes two ways, with different consequences: | | `require` / `include` | `opcache_compile_file()` | |---|---|---| | Executes the file | yes | no, compiles only | | Nested includes | followed and preloaded | not followed | | Conditional declarations | supported | not supported | | Load order | parents first | any order | A class whose parent, interface or trait is not available at the end of preloading cannot be linked; OPcache skips it with a "Can't preload unlinked class" warning. Preloading a class that is already declared also warns. ## What you give up 1. **Hot changes.** Preloaded symbols live until the PHP process restarts. `opcache_reset()` and file validation do not replace them, so a deploy that changes preloaded code must restart or reload the PHP server. That is why the manual calls preloading practical only in production. 2. **Baseline memory.** Everything preloaded occupies shared memory whether any request uses it or not. "Preload everything" is the simplest strategy and not necessarily the best. 3. **Constants.** Global constants defined in preloaded files are not preloaded; if code depends on them, the file must still be included at runtime. 4. **Redefinition rules.** If a request includes a preloaded file again, its top-level code runs but its symbols are not redefined. `include_once` does not prevent that second inclusion. 5. **Platform and context.** Preloading is not supported on Windows, and it is pointless for ordinary CLI scripts, which start a fresh process each time. ## Running as root Preloading executes PHP code at server start, often while the server still runs as root. OPcache refuses to do that by default: without `opcache.preload_user` set, startup stops with a fatal error that the directive is required when running under uid 0. Set it to the unprivileged account the workers use. Since PHP 8.3 the CLI and phpdbg SAPIs no longer require it. ## Checking what was preloaded `opcache_get_status()` includes a `preload_statistics` section when preloading is active, with the preloaded `functions`, `classes` and `scripts` and the memory they use. Run it from inside the pool to confirm that the classes you expected were actually linked; a class that hit the "unlinked" warning is simply absent, and the application falls back to autoloading it on every request, silently losing the benefit. ## Preloading and deploys Because preloaded code is fixed for the process lifetime, preloading pushes a deploy towards restarting PHP rather than resetting OPcache. Teams that already restart or replace PHP processes on every release lose nothing; teams that rely on in-place resets must add a restart, or keep frequently changing code out of the preload list so that ordinary resets keep working for it. ## Is it worth it? The benefit is that per-request autoloading and linking of the preloaded classes disappears. For frameworks that load hundreds of classes on every request, that can be a measurable improvement; for an application dominated by database and network time, it is small. Practical guidance: - Preload the classes almost every request uses — the framework kernel, the container, common value objects — rather than the whole `vendor/` tree. - Measure throughput and memory with and without preloading on production-like traffic. - Make the deploy restart PHP-FPM whenever preloaded files change, and treat the preload file list as build output generated with the release. - Keep development without preloading, so edited classes take effect immediately.
- Why does opcache_reset() not pick up a change to a preloaded class?Preloaded symbols are stored for the lifetime of the server process and are not part of the cache that a reset clears. Only restarting or reloading the PHP server runs the preload script again and replaces them.
- When would you choose require over opcache_compile_file() in a preload script?When the files declare functions or classes conditionally, or include further files themselves: `require` executes the code, so conditional declarations and nested includes are preloaded. `opcache_compile_file()` only compiles, but lets you load classes in any order, which suits autoloaded code.
saying these in an interview costs you the question
- Preloaded classes update after opcache_reset()
- Preloading also makes global constants available
- Preloading speeds up one-off CLI scripts
- Preloading the whole vendor directory is always best
- opcache_compile_file() executes the file's top-level code