env.php is small, critical, and easy to get wrong
The app/etc/env.php file is one of the most important files on a Magento store and one of the least reviewed. It holds database credentials, cache and session backends, the deploy mode, and the encryption key.
When it is wrong, misaligned across environments, or silently overriding admin settings, the results are confusing. Configuration that "should" be one value behaves as another, and nobody can find where the real value lives.
This article covers what env.php controls, how configuration precedence works across env.php, config.php, and the database, and how to keep the whole picture consistent.
What env.php actually controls
The file is the environment-specific heart of the store. Its contents decide how the application connects to everything around it:
- Database connection details, including host, name, and credentials.
- Cache and session backends, such as Redis or Valkey configuration.
- The deploy mode, through
MAGE_MODE. - The encryption key, used for encrypting stored credentials and sensitive data.
- The list of enabled cache types.
Each of these is environment-specific by design, which is why env.php is not committed to version control and differs between staging and production.
The encryption key is not replaceable
The encryption key deserves special care. Magento uses it to encrypt values stored in the database, including payment and integration credentials.
This makes the key a backup priority, not just a config value. It should be recorded somewhere safe and kept aligned with any database copy, or the copy is partially unreadable.
How configuration precedence works
Magento reads configuration from three places, and they override each other in a specific order. The database holds the base values in core_config_data, config.php holds shared configuration in code, and env.php holds environment-specific overrides.
Values in env.php take precedence over the database. This is powerful and confusing at once, because a setting configured in the admin can be silently overridden by a value in env.php that nobody remembers adding.
Understanding this order is the key to diagnosing "I changed it in the admin and nothing happened." The admin writes to the database, but env.php wins.
Config path drift across scopes
Configuration also has scope. A value can be set at the default level, the website level, or the store-view level, and the most specific scope wins for a given store.
Drift happens when the same setting is configured at multiple scopes with different values, and nobody tracks which one is authoritative. A setting that looks correct at the default level can be overridden at the website level in a way that is easy to miss.
The bin/magento config:show command reports the effective value and its scope, which is how you find where a setting is really coming from.
config.php and locked configuration
Running bin/magento app:config:dump exports configuration into config.php and locks those values, so they can no longer be changed from the admin. This is intended to make configuration reviewable and consistent across environments.
It also surprises people. Once a setting is locked into config.php, the admin field for it becomes read-only, and changes have to go through code and deploy instead.
This is the right pattern for configuration that should be identical everywhere. The confusion comes only when nobody documents that a setting was locked, so an admin user cannot understand why the field will not change.
Keeping env.php secure
Because env.php holds credentials and the encryption key, its permissions matter. It should be readable by the application and not exposed, and it should never be world-readable on the server.
It also should not leak into places it does not belong. A copy of env.php in a backup archive, a shared drive, or a support ticket is a credential exposure, because it contains everything needed to connect to the database.
Treat it as a secret file, because that is what it is. The database password and encryption key inside it are as sensitive as any credential the store holds.
Diagnosing configuration confusion
When a setting behaves unexpectedly, work down the precedence order. Check env.php first, then config.php, then the database value and its scope with config:show.
The effective value comes from the highest-priority source that defines it, so the answer to "why is this setting this value" is almost always one of those three. Reading them in order turns a mystery into a lookup.
Doing this across environments also surfaces drift, where the same setting resolves differently on staging and production because it is defined in different places on each.
A small file worth reviewing
env.php and the configuration precedence around it are easy to ignore until they cause a confusing problem. A wrong deploy mode, a lost key, or a silent override can each cost hours if you do not know where to look.
Knowing what env.php controls, how it overrides the database, and where your configuration actually resolves removes a whole class of confusion. That configuration integrity check is a quick, high-value part of any infrastructure review.