Feature Request: Allow Partial Overrides for .env.[environment] Files Instead of Full Replacement
Summary
Many modern tools—including Bun and dotenvx—have popularized the use of .env.* files (e.g., .env.production, .env.development) to override values in .env. However, dotenv-vault fully replaces the target environment when pushing a file, causing any variables not in the pushed file to be lost.
A partial override workflow would bring dotenv-vault more in line with the common “base + environment-specific override” pattern.
The Problem
-
Loss of Existing Variables
- If
.env.productiondoesn’t contain all necessary variables, pushing it toproductionremoves any keys not listed.
- If
-
Misalignment with
.env.*Patterns- Tools like Bun, dotenvx, and others expect
.env.productionto override values from.env, not replace them entirely. Dotenv-vault's current behavior breaks this expectation.
- Tools like Bun, dotenvx, and others expect
Proposed Solution: Partial Override
-
Only override the keys present in
.env.[environment].- If a key exists in
.env.production, overwrite (or add) it. - If a key does not exist in
.env.production, preserve its existing value in the vault.
- If a key exists in
How It Could Work
CLI-Level Merge
On dotenv-vault push production .env.production, the CLI would:
-
Pull existing variables from
production. -
Merge them with the local
.env.production(where any duplicates in.env.productionoverride existing values). -
Push the merged result back to
production.
This ensures any variables not declared in .env.production remain unchanged in the vault.
Flags and Options
- A
--mergeflag (or similar) to explicitly enable partial overrides. - A
--allor--baseoption to push.envacross all environments, providing a common starting point for overrides.
Limitations
-
Not Actually Syncing Layered Files
- Pulling from the vault retrieves only the final compiled
.envfor a given environment (e.g.,production,development). You don’t get separate.envand.env.productionfiles back—just the merged result.
- Pulling from the vault retrieves only the final compiled
-
Potential for Environments Getting Out of Sync
- Since dotenv-vault doesn’t natively support true layered environments, environments can drift apart over time.
- Example scenario:
- You push
.env(shared base variables). - You push
.env.production(overriding production-specific values). - Later, you push
.envagain—this fully replaces the environment, wiping out values previously overridden by.env.production.
- You push
- This means pushing
.envlater does not preserve per-environment overrides, requiring manual tracking of all expected values.
-
dotenv-vault design and use case needs
- In a true layered system, you push
.envonce and then independently push per-environment overrides without losing values. - However, dotenv-vault only stores the final resolved environment, not the separate
.env.*files. - Unlike Bun and dotenvx, where
.envand.env.productionare dynamically merged at runtime, dotenv-vault environments are static snapshots—meaning each push must fully account for all values, not just overrides.
- In a true layered system, you push
Why This Proposal is Still a Good Compromise
- Implementing true layered environments would likely require major changes to how dotenv-vault stores and manages variables.
- This proposal minimizes destructive behavior by allowing partial overrides, while keeping the existing vault structure intact.
- It still requires some manual tracking when updating environments, but it’s significantly less risky than the current full-replacement behavior.
Potential Impact
-
Infrastructure/Security
- Minimal, as the logic change is entirely CLI-side. The vault would still store only the final merged result.
-
Backward Compatibility
- Could be opt-in (e.g., via a
--mergeflag), allowing current full-replacement behavior to remain the default if desired.
- Could be opt-in (e.g., via a
some great feedback here @notnotjake.
I'm the creator of both - dotenv-vault and dotenvx. right now i'm directing more of the team's efforts toward dotenvx and then longer term - beginning of 2026 i think - i'll begin merging both tools together. at that time we'll address all or most of this.
@motdotla It would be great to have a feature where we can disable "synced" env environments on dotenv-vault. One where we can remove 1:1 syncing. I might want my .env.staging to stay completely different to my .env file. But if I push .env it looks like dotenv-vault is telling other environments to base off of .env or whatever the main is and I might want my .env.staging to be completely disconnected and not include some vars from .env or contain ones specific to staging and don't want that to trickle into other environments.
Hope I explained that well. Something that I'm running into and is somewhat similar to this feature request.
Which actually relates almost 1:1 of this mention in the main request: "Unlike Bun and dotenvx, where .env and .env.production are dynamically merged at runtime, dotenv-vault environments are static snapshots—meaning each push must fully account for all values, not just overrides." and or keeping various variables on specific environments and not all values on all environments.