codegenie-be / laravel-config-cache-guard
Prevent Laravel from using stale config or route cache after deployment changes, with Composer autoload integration and in-app auto repair for shared hosting.
Package info
github.com/Codegenie-BE/laravel-config-cache-guard
pkg:composer/codegenie-be/laravel-config-cache-guard
Requires
- php: ^8.2
- illuminate/console: ^12.0|^13.0
- illuminate/support: ^12.0|^13.0
Requires (Dev)
- larastan/larastan: ^3.10
- laravel/pint: ^1.0
- orchestra/testbench: ^10.0|^11.0
- pestphp/pest: ^3.0|^4.0
- symfony/process: ^7.2|^8.0
This package is auto-updated.
Last update: 2026-08-20 15:45:41 UTC
README
by Codegenie
Laravel Config Cache Guard is a zero-configuration safety and performance layer for Laravel config and route cache. It prevents known-stale deployment cache from being loaded before Laravel boots, automatically creates missing caches when Laravel supports them, and repairs cache after the HTTP response without making visitors wait for Artisan compilation.
Quick start
composer require codegenie-be/laravel-config-cache-guard
That is enough for the normal flow. No public/index.php change and no CONFIG_CACHE_GUARD_* variable is required.
Optionally inspect the current state with:
php artisan config-cache-guard:status
Default behavior
On normal HTTP traffic the package:
- protects existing config cache before Laravel can load stale configuration
- protects existing route cache before stale routes can be dispatched
- automatically queues missing config and route cache creation after the response
- never starts a child PHP process or waits for a repair lock before Laravel boots
- performs cache generation through Laravel's own
Artisan::call()after the response - serializes config and route mutation behind one non-blocking deployment repair lock
- uses a deployment source manifest so healthy requests verify known sources without recursively rediscovering them
- stores signature-based route-cache copies when the default Laravel route-cache path is used
- works without SSH, Redis, queues, workers, cron, a database or a public repair endpoint
Request path
The visitor-facing path deliberately contains detection and protection only:
HTTP request
-> Composer loads bootstrap/guard.php
-> verify known deployment source state
-> current cache: continue immediately
-> stale config: remove it and queue repair
-> stale routes: bypass/remove them and queue repair
-> Laravel boots with safe cached or uncached state
-> HTTP response is sent
-> one terminating request acquires the non-blocking repair lock
-> config:cache and/or route:cache run only when required
-> signatures and the deployment source manifest are refreshed
The pre-bootstrap guard does not run php artisan, does not call proc_open() and does not wait for another request to finish cache compilation.
Deployment source manifest
The active Laravel bootstrap cache directory contains a small file:
deployment-source.manifest.json
It stores only:
- relative source paths
- filesystem metadata fingerprints, or one-way content hashes in content mode
- directory fingerprints used to detect added/removed source files
- the current config and route signatures
- a one-way runtime identity for config portability checks
It does not store .env values or raw application base paths.
When the manifest is current, the guard avoids repeated RecursiveDirectoryIterator discovery. It checks the already-known source files and directories directly. When a file or source directory changes, the manifest is rebuilt from one shared traversal and both config and route signatures are derived from that same snapshot.
Sources covered
Deployment state includes:
.env.env.{APP_ENV}whenAPP_ENVis available before Composer loadsconfig/**/*.phproutes/**/*.phpapp/Providers/**/*.php- the active bootstrap
app.phpandproviders.php composer.jsoncomposer.lock
Config signatures also include a one-way runtime identity derived from the application location and OS family. A config cache signed at another runtime path is therefore not assumed to be portable.
The default signature mode uses filesystem metadata. Optional content mode hashes source bytes to detect same-size rewrites that preserve file metadata.
Missing cache creation
If config cache is missing, the package queues config:cache after the current response.
If route cache is missing, the package queues route:cache after the current response.
This is fail-safe:
- a failed cache build is removed instead of retained as untracked state
- routes that Laravel cannot cache continue through normal uncached routing
- a failed source signature is remembered for a bounded cooldown so identical source state is not retried on every request
- when source state changes, the package can immediately try again
Laravel config-cache contract
Automatic config caching assumes normal Laravel production conventions: use env() inside configuration files and read values elsewhere through config().
config('services.mailgun.secret');
Direct env() access in application code outside config/*.php can behave differently after config:cache is enabled and should be corrected before production caching is relied on.
Route cache behavior
When Laravel uses its default route-cache location, a successful route build is also tracked as:
bootstrap/cache/routes-<source-signature>.php
The pre-bootstrap guard points Laravel at the route cache for the current source signature. If that file does not exist, Laravel falls back to uncached route registration for the current request while repair is queued. An old route cache can remain on disk without being selected.
Explicit custom APP_ROUTES_CACHE paths remain supported when they are available before Composer loads. Stale custom route cache is removed rather than redirected to a package-managed versioned path.
Concurrency
Deferred cache mutation uses one file:
deployment-cache-repair.lock
The lock is non-blocking. If 20 requests finish at the same time after a deployment, one worker performs the pending config/route repair and the others return from termination without waiting.
Config and route cache commands are executed sequentially by that one repair owner, avoiding simultaneous deployment-cache mutation by different workers.
Native deployment commands
A deployment pipeline with command access can still build caches explicitly:
composer install --no-dev --prefer-dist --optimize-autoloader --no-interaction php artisan config:cache php artisan route:cache php artisan config-cache-guard:status --strict
Only run route:cache manually when the application's routes support Laravel route caching.
Successful native cache commands are tracked automatically. The package records current deployment signatures and prepares the signature-based route cache where appropriate.
Shared hosting and FTP-only deployments
Destination-side shell access is optional.
For FTP-only or restricted shared hosting:
- package or install production Composer dependencies before upload
- upload a clean release instead of overlaying an old vendor tree when possible
- preserve the production
.env - keep Laravel's active bootstrap cache directory writable by PHP
- send normal HTTP traffic
Missing cache is generated after a response. Existing stale cache is rejected or bypassed before Laravel uses it. No PHP CLI binary has to be configured for the HTTP fallback.
See deployment recipes for concrete flows.
Status command
php artisan config-cache-guard:status
The command reports active cache paths, deployment-source manifest state, config/route signatures, pending and failed repair state, recent successful repairs and the shared deferred repair lock.
Use strict mode in deployment automation:
php artisan config-cache-guard:status --strict
Clear intentionally resolved failure state with:
php artisan config-cache-guard:status --clear-failures
Optional overrides
The normal package behavior needs no package-specific environment variables. Existing compatibility overrides remain available when configured before Composer loads, including:
- disabling the complete guard or one cache target
- disabling automatic after-response repair
- selecting
contentsignature mode - disabling signature-based route cache files
- enabling fail-hard diagnostics
- changing the failure retry cooldown
Laravel's own optional cache path overrides are also respected:
APP_CONFIG_CACHEAPP_ROUTES_CACHE
No override is required for standard Laravel paths.
Files written by the package
Depending on active cache state, the Laravel bootstrap cache directory can contain:
config-source.signature
route-source.signature
deployment-source.manifest.json
deployment-cache-repair.lock
config-cache-refresh.pending
config-cache-refresh.failed
config-cache-refresh.succeeded
route-cache-refresh.pending
route-cache-refresh.failed
route-cache-refresh.succeeded
routes-<source-signature>.php
Markers contain safe reason/action metadata and optional one-way source signatures, never .env values or command output.
Requirements
- PHP 8.2 or higher
- Laravel 12 or 13
- writable active Laravel bootstrap cache directory (
bootstrap/cacheor.laravel/cache) - writable configured cache destination when a custom Laravel cache path is used
Failure behavior
| Situation | Behavior |
|---|---|
| Cache and manifest are current | Verify known sources and continue. |
| Config cache is missing | Queue config:cache after the response. |
| Route cache is missing | Queue route:cache after the response. |
| Route cache cannot be created | Continue with uncached routing and remember the source signature for the retry cooldown. |
| Config source/runtime state changed | Remove stale config before Laravel can load it and queue repair. |
| Route source state changed | Point Laravel away from stale routes and queue repair. |
| Repair lock is held by another request | Return immediately; do not duplicate repair. |
| Sources change during repair | Discard the just-built cache and requeue the new signature. |
| Rebuilt cache signature cannot be stored | Remove the untracked cache. |
| Known-stale cache cannot be removed | Stop with a safe 503 rather than load known-stale state. |
Development
Install development dependencies and run:
composer install composer check:all
Before a release, also run:
composer test:e2e composer check:release
The repository validates Laravel 12 and 13 across their supported PHP matrix and includes Windows, macOS, Linux ARM64 and Alpine portability coverage.
Security and privacy
- no
.envvalues are logged or persisted - raw runtime filesystem paths are not persisted in deployment signatures or the source manifest
- no data is sent to an external service
- no database, Redis, queue, worker or cron dependency is required
- cache/signature/manifest writes are atomic
- stale deployment cache is never knowingly preferred over safe uncached execution
Report security issues privately. See SECURITY.md.
License
MIT. See LICENSE.md.