😵 Why Drupal Config Keeps Changing When “Nothing Changed”
Date: 2026-06-26
✨ Summary
If you run drush cst, drush cex, or compare config/sync against the active database config, Drupal can report differences even when nobody intentionally changed site behavior.
Sometimes the diff is real.
Sometimes it is only:
- YAML key order changes
- translated labels leaking into base config
langcodeor config-language drift
This is a known Drupal pain point. It is not one single bug. It is a combination of:
- configuration serialization details
- multilingual config override behavior
- config entities being saved in the current admin language
🧩 The Short Version
There are 3 main reasons this happens:
- Order-only serialization drift
- Language overrides leaking into base config
- Config language /
langcodechurn
So yes: this is a known Drupal issue family.
But the exact cause depends on the kind of diff you are seeing.
1. 🔀 Order-Only Serialization Drift
Sometimes Drupal stores the same config values in a different key order.
That means:
- the meaning is unchanged
- the behavior is unchanged
- but the YAML file is different byte by byte
This is why drush cst can show a config item as “Different” even though the only change is the order of nested keys.
Typical examples
- menu overrides where keys move around
- field widget or drag/drop config where one nested item is moved lower in the file
- display/form config where maps are serialized in a slightly different order
Current example from this project
The recent drush cst output showed:
core.menu.static_menu_link_overridesfield.field.node.page.field_paragraphs
In both cases, the values were the same. Only the YAML order differed.
That is harmless config drift, not a functional site change.
Relevant Drupal core issue
#2852557 Config export key order is not predictable, use config schema to order keys for maps- Status: Closed (fixed)
- Link: https://www.drupal.org/project/drupal/issues/2852557
This issue fixed a lot of ordering instability in core, but not every possible nested save path or contrib interaction.
Related issue
#3480248 Drupal does not recognize when the config is identical- Link: https://www.drupal.org/project/drupal/issues/3480248
This is closely related to the same general class of problem: Drupal still sometimes treats semantically identical config as different.
2. 🌍 Language Overrides Leaking Into Base Config
Drupal has a configuration override system.
One important override type is language overrides.
That is a useful feature, but it becomes dangerous when a config entity is loaded with overrides active and then saved back into the original storage.
When that happens, translated labels can leak into the base config.
What this looks like in real life
You translate something in German, French, or Dutch.
Then later:
- a block is saved
- a View is edited
- a menu item is reordered
- a field or display config entity is saved
And suddenly the exported base config contains translated labels or changed values in the “wrong” language.
Why it happens
Drupal’s config system conceptually separates:
- loading config with overrides
- loading editable config that should be saved
But in practice, config entities can still be saved after being loaded with overrides, and that causes override values to be written back to the original config.
Relevant Drupal core issue
#2910353 Prevent saving config entities when configuration overrides are applied- Status as of 2026-06-26: Needs work
- Link: https://www.drupal.org/project/drupal/issues/2910353
This is one of the most important issues behind config-language drift and translated-label corruption.
Related duplicate issue
#3117709 Avoid mixed languages in configuration sync- Status: Closed (duplicate)
- Duplicate of
#2910353 - Link: https://www.drupal.org/project/drupal/issues/3117709
3. 🏷️ Config Language / langcode Churn
Another class of problem is when configuration language changes unexpectedly.
This often happens on multilingual sites when:
- a module is installed
- a theme is installed
- the site default language is not English
- development is done in a translated admin interface
Common symptom
You create fields or config in one language, export config, and later:
- labels are exported in another language
langcodechanges- extra language-specific config appears
- config that used to look stable suddenly looks mixed
Relevant Drupal core issue
#3150540 Configuration langcode is forced to site default language- Status as of 2026-06-26: Needs work
- Link: https://www.drupal.org/project/drupal/issues/3150540
This issue is especially relevant for teams that want a single canonical config language, often English, even when the site default language is something else.
📚 Useful Core Documentation
Configuration management
- Drupal configuration management docs:
- https://www.drupal.org/docs/administering-a-drupal-site/configuration-management
Configuration override system
- Drupal configuration override system docs:
- https://www.drupal.org/docs/drupal-apis/configuration-api/configuration-override-system
This is especially relevant because language overrides are stored as configuration too, and they are part of the bigger story here.
🧪 Important Clarification About drush cst
drush cst is read-only.
It does not create changes.
It only compares:
- active config in the database
- sync config in
config/sync
So if drush cst reports differences, that means drift already exists.
It does not mean cst caused the drift.
✅ Can We Prevent It Completely?
No, not completely.
But we can reduce it a lot.
🛡️ Best Practices To Reduce Config Noise
1. Choose one canonical config language
Pick one admin/config language for structural work.
Usually:
- English
This does not mean the site frontend must be English.
It means the team treats one language as the source-of-truth language for config authoring.
2. Do config work only in that language
Avoid saving config entities while using a translated admin UI if your team expects config exports to stay in one canonical language.
That includes editing:
- fields
- form displays
- view displays
- menus
- Views
- blocks
- paragraph types
3. Use one environment as the config-authoring source of truth
A healthy workflow is:
- one designated environment or branch is used to create/export config
- other environments mostly import config
In practice:
- on dev/stage/prod that should follow the repo: use
drush cim - only on the config-authoring workflow: use
drush cex
That reduces accidental export churn from random environments.
4. Be careful after module or theme installs
On multilingual sites, module/theme installs are common moments for config language churn.
After installs:
- inspect
drush cst - inspect
git diff - do not assume all exported changes are intentional
5. Do not hide structural config drift with ignore rules
It is tempting to use ignore/split/filter modules to hide noisy config.
That can be valid for true environment-specific config.
But for structural config like:
- field definitions
- menus
- display config
ignoring it usually hides real problems instead of solving them.
6. Review config diffs before exporting or committing
This sounds obvious, but it matters more in Drupal than in many frameworks.
A good habit:
- run
drush cst - inspect the exact files
- decide whether the differences are:
- functional changes
- order-only drift
- translation/langcode noise
Only then decide whether to:
- import sync config
- export active config
- or discard UI changes
7. Treat “translated labels in config” as suspicious
If your team expects canonical English config, and suddenly a label appears in German or French, that is usually not random.
It often means:
- config was created in another admin language
- a config entity was saved with language overrides active
- multilingual behavior leaked into base config
That is worth investigating before committing.
🔎 A Practical Rule Of Thumb
When config changes appear, ask:
Is this a real behavior change?
Examples:
- new field
- new paragraph bundle
- changed route settings
- changed enabled/disabled flags
- changed IDs/slugs/query values
If yes, it is probably intentional config work.
Or is this only serialization/language noise?
Examples:
- same keys, different order
- same values, different line order
- label text switched language
langcodechanged unexpectedly
If yes, it is probably Drupal config drift, not product work.
🧭 What To Do When You See Drift
If the repository is the source of truth:
ddev drush cim -y
ddev drush cst
If the database state is intentionally the new source of truth:
ddev drush cex -y
But that second option should only happen when you are sure the active config changes were intentional.
🧱 Final Takeaway
Drupal config drift is real, common, and often confusing. 😅
The most important things to remember are:
- not every config diff is a real site change
drush cstdoes not create drift, it only reports it- multilingual admin/config workflows are a major source of noise
- there are real, known core issues behind this behavior
- you can reduce the problem with discipline, but not fully eliminate it
The most useful mental model
Think of Drupal config drift as a mix of:
- serialization noise 🧾
- multilingual override leakage 🌍
- config-entity save behavior 🛠️
Once you separate those three categories, the diffs become much easier to reason about.
🔗 Reference Links
-
Drupal config management docs
https://www.drupal.org/docs/administering-a-drupal-site/configuration-management -
Drupal configuration override system docs
https://www.drupal.org/docs/drupal-apis/configuration-api/configuration-override-system -
#2852557 Config export key order is not predictable, use config schema to order keys for maps
https://www.drupal.org/project/drupal/issues/2852557 -
#3480248 Drupal does not recognize when the config is identical
https://www.drupal.org/project/drupal/issues/3480248 -
#2910353 Prevent saving config entities when configuration overrides are applied
https://www.drupal.org/project/drupal/issues/2910353 -
#3117709 Avoid mixed languages in configuration sync
https://www.drupal.org/project/drupal/issues/3117709 -
#3150540 Configuration langcode is forced to site default language
https://www.drupal.org/project/drupal/issues/3150540