Laravel config:cache: env() resolution across local and production configuration boundaries
0 reputation · 02 Feb 2021, 00:25 UTC
0 reputation · 02 Feb 2021, 00:25 UTC
Laravel's configuration caching feature (php artisan config:cache) alters when env() calls are evaluated. Without caching, env() in configuration files resolves at runtime. With caching, those calls are evaluated once while the configuration is serialized, and later requests read the cached array.
This creates a local-to-production boundary: local development often skips caching, while production deployments commonly run config:cache. If an environment variable is not present during caching, the cached value can become null, even though the same code works locally. Laravel's documentation recommends using env() only within configuration files and accessing values elsewhere through config(). Assuming a Laravel version that supports configuration caching, such as 10 or 11, verification requires comparing how env() resolves when configuration is cached versus uncached.
The unresolved decision concerns env() calls that already exist outside configuration files, and how to treat environment variables that change after caching. Should such calls be refactored to config(), or should the relevant values be moved into a configuration file before caching? What behavior should be expected when an environment variable is added or changed after config:cache has run?
35275 reputation · 02 Feb 2021, 11:23 UTC
Move the value into a configuration file and reference it with config() in application code. Do not call env() directly in controllers, service providers, or other classes when config:cache is active. When an environment variable is added or changed after config:cache has run, every config() value derived from that variable remains frozen at the cached value until you clear and rebuild the cache. By contrast, env() calls outside config/ still evaluate at request time and will see the new value, producing inconsistent state.
In Laravel 10 and 11, running php artisan config:cache loads every file under config/, evaluates each env() call once, and serializes the resulting array. Subsequent requests read that array directly. The cache does not wrap or intercept env() calls made elsewhere in the codebase; those calls hit the runtime environment on every request. This is why local development—where caching is often skipped—can behave differently from a production deploy that caches configuration.
env( outside the config/ directory.config/services.php) using env('KEY', 'default').env() call in application code with config('services.key').php artisan config:cache..env, trigger a request, and confirm config() still returns the old cached value while a raw env() call returns the new one. Then run php artisan config:clear && php artisan config:cache to confirm the new value is picked up.Once the cache exists, adding or editing an environment variable has no effect on config() until the cache is regenerated. If the variable was missing when config:cache executed, the cached value is null and stays null. This is intentional: the cache trades runtime flexibility for faster bootstrap.
Are the env() calls outside config/ in application code you control, or inside third-party packages? If they are in packages you cannot modify, you cannot refactor them to config(). In that case, ensure the variable is present in the environment before config:cache runs, and treat any post-cache changes as visible only to those package calls—not to your application's config() values.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.