What is configuration drift between environments?
On this page
Configuration drift is the gradual divergence of settings between environments that are supposed to differ only in deliberate ways, so that development, staging and production end up with different sets of variables or unexpected differences in values, and code that works in one fails in another.
How it shows up
Drift is rarely one big change. It is many small ones that nobody wrote down:
- A developer adds
REDIS_URLlocally and to production during an incident, but not to staging. - A feature flag is turned on in staging for a demo and never turned off.
- Production gets a new API key after a rotation; staging still uses one tied to a former employee's account.
- The .env.example in the repository lists variables that the code stopped reading a year ago.
The Twelve-Factor App names the underlying goal: "Keep development, staging, and production as similar as possible" (Twelve-Factor App). Its gaps of time, personnel and tools are also where config drifts: changes made by different people, at different times, through different tools.
Why it hurts
- Releases fail late. The bug that only appears in production is often a variable that only exists in staging.
- Tests stop meaning anything. A staging environment with different settings tests a different system.
- Security gaps hide in the difference. Debug mode left on in one environment, or a production database password reused in staging, is drift too.
Drift you want, drift you don't
Environments are supposed to differ. Production uses live payment keys and a production database; development doesn't. The useful distinction is between names and values:
- Variable names should usually match across environments. A name present in one and missing in another is almost always drift.
- Values should differ where the environment's purpose requires it, and match where it doesn't, such as timeouts, feature settings or log formats.
Checking names is cheap and catches most problems. The compare two .env files tool does it in the browser for two files you paste.
Common mistakes
- Copying the whole file from production to staging. That fixes drift by spreading production secrets into a less protected place.
- Fixing drift by hand during an incident and not recording it in the source of truth.
- No single source. If each server's file is its own source, drift is guaranteed.
How Crunu helps
Compare environments puts two environments side by side, for example payments-api / staging and payments-api / production. It shows which variables exist only on one side, which differ and which match, with values hidden until you choose to show them. The comparison runs in your browser, so the server doesn't learn which values match.
From the same screen you can copy selected values from one environment to the other. The copy is saved as a new signed version of the target, and the previous values stay in its history. You need edit rights on the target, so a developer who can edit staging can't push into production. Keeping environments in sync as a routine is covered in how to share .env files with your team.
Sources
- The Twelve-Factor App: X. Dev/prod parity, checked October 30, 2026.
From the blog
Practices
Keeping .env.example in sync with every environment
A .env.example drifts because nothing breaks when it's wrong. Compare names, never values, fail CI on missing variables, and compare real environments.
Sharing .env files guide
CI/CD
Bitbucket Pipelines OIDC: the step token explained
What oidc: true gives a Bitbucket step: the BITBUCKET_STEP_OIDC_TOKEN, the workspace issuer, audiences, the sub claim and how to pin a trust policy to it.
CI and OIDC guide
CI/CD
GitHub's new OIDC subject format: fixing AWS trust policies
Not authorized to perform sts:AssumeRoleWithWebIdentity on a new repo? GitHub added owner and repo IDs to the OIDC sub claim. How to check and fix the policy.
CI and OIDC guide