Independent comparison · no paid rankings
Home / Blog / Invalidating OPcache during deployment without serving old code
Technical

Invalidating OPcache during deployment without serving old code

Deploying PHP without touching OPcache bets that no worker keeps old compiled bytecode — until the next ghost bug.

4 min read Updated Jul 19, 2026

Bug fixed in production — ticket closed. Users still see the error. CDN cache? Purged. Opcode? opcache.validate_timestamps=0 from "performance" tuning: PHP files updated on disk, old bytecode served forty minutes until a panicked manual PHP-FPM restart.

OPcache is acceleration — mishandled in production, it is a code cache ignoring your deploys. The goal is not "clear cache"; it is syncing filesystem release and PHP workers without triggering a cascade of 502 errors.

Healthy deploy cycle

A reliable PHP deploy follows a documented sequence:

  1. Atomic release: /releases/20260719/ + symlink current.
  2. Composer install, migrations, app cache warm-up.
  3. php artisan optimize or Symfony cache if applicable.
  4. Reload PHP-FPM: systemctl reload php8.2-fpm (graceful).
  5. Smoke test on health endpoint.
  6. Rollback = revert symlink + reload.

reload recycles workers progressively — in-flight requests finish; new workers load fresh OPcache. A brutal restart causes outage; reload is the preferred choice for zero-downtime deploy.

Brutal restart vs graceful reload: the first interrupts service; the second preserves in-flight connections.

validate_timestamps: the trade-off to understand

SettingBehaviorUse
validate_timestamps=1stat file, recompile if mtime changesDev, staging
validate_timestamps=0never recheck diskProduction + reload each deploy

With revalidate_freq=0 and validate=1, every request checks disk — useless IO in production. The pair validate_timestamps=0 + scripted FPM reload is the standard for teams deploying several times per week.

Invalidation strategies

A — FPM reload (recommended) Post-deploy step in script: systemctl reload php-fpm. Simple, predictable, no major interruption.

B — CLI opcache_reset() post-deploy Via SSH one-shot — acceptable with a single PHP-FPM pool. Never in an HTTP request.

C — Rolling deploy on N servers Load balancer drain → deploy → reload → re-enable. Zero downtime on a cluster.

D — opcache.file_cache Second level on disk — watch sync across nodes during deploy.

Multi-version and container traps

  • Blue-green with two releases: mixed workers if partial reload — finish reload on all nodes before switching traffic.
  • Preloading PHP 7.4+: preload file change requires full restart, not simple reload.
  • Docker: new image = new container, fresh OPcache. Volume-mounted code = same validate_timestamps issue.

On shared hosting, no self-service FPM reload — FTP deploy with forced validate_timestamps=1 or support ticket. More reason for VPS or PaaS if you deploy frequently.

The peak: OPcache without deploy procedure is involuntary A/B testing

Here is what "performance" settings forget to document.

PHP deploy checklist: documented symlink + FPM reload — not "upload and hope."

Decide and move forward without blind spots

In half a day you can secure your PHP deploys:

  1. Set validate_timestamps=0 in production with scripted FPM reload.
  2. Implement atomic deploy via symlink.
  3. Make mandatory a smoke test post-reload.
  4. Ban opcache_reset() in web endpoints.
  5. Plan rolling deploy if you have multiple servers.

Document the full sequence in your deploy runbook: who triggers reload, how to verify all workers recycled, and which test confirms new code is served. Cross-read PHP profiling to measure bad deploy impact, and Blue-green deployment for multi-instance architectures.

Frequently asked questions

Why does old code run after deploy?

OPcache keeps compiled bytecode in memory. With validate_timestamps=0, changed files on disk trigger no reload until a worker is recycled via FPM reload.

Is opcache_reset() safe in prod?

Not in a web request — it is a brutal global reset. Prefer graceful PHP-FPM reload or CLI reset post-deploy, outside user traffic.

validate_timestamps=1 in production?

Fine for staging. In production it adds stat() calls on every include. The common compromise remains validate_timestamps=0 + FPM reload each deploy.

Does atomic deploy help?

Yes. Symlink switch + FPM reload syncs all workers on the same file tree, without mixing old and new releases.


After deploy, if OPcache was not invited, you run two site versions — one in git, one in RAM.

Compare European hosts

Filter by compliance, location and use case — then open the sheets to verify the real scope.

Browse the directory
Blog

Related reading

All articles →