Article

Config-as-code with Config Split: never cex what a split is hiding

Config Split keeps env-specific configuration out of the canonical sync directory, but running drush cex while a split is active deletes the split-owned files from config/sync. The safe model: hand-edit the split's member lists, verify with cim instead of cex, and route per-environment values through settings.php overrides rather than the split.
July 14, 2026
Topics:Configuration Management
Tags:DrupalDrush

Drupal's Config Split keeps environment-specific configuration out of your canonical sync directory — dev tooling, a dev-only permissions tier, per-environment overrides. It works well until someone runs drush cex with a split active and half of config/sync disappears from the diff. Here is the model that avoids that.

What it solves

You want one canonical configuration that deploys to production, plus a few things that exist only in development — Devel, a broader agent-permission tier, verbose logging. Config Split lets a named split own those items so they live in a separate folder and activate conditionally (keyed on an environment variable), while the shared config stays in config/sync.

The trap: cex with a split active

When a split is active, its items are removed from the main export set. Run drush cex in that state and Config Split does exactly what it is designed to: it writes the reduced configuration and deletes the split-owned files from config/sync. If you did not intend to re-partition, you have just staged the deletion of a large part of your canonical config. The git diff is alarming, and if you commit it, the next deploy imports the deletion.

The working model

  • Do not cex with a split active. Treat the split's member lists as hand-edited config: add or remove an item by editing the split's own complete_list / partial_list, not by exporting.
  • Verify with cim, not cex. After editing, run drush cim and confirm it reports the change you intended and nothing else. Import is non-destructive to your source of truth; export, under a split, is not.
  • Env-specific values do not belong in a split at all. A different OAuth client per environment, a secret, a hostname — put those in a settings.php $config[...] override that reads from the environment. Config Split is for env-specific items (this module or profile exists only here), not per-environment values of a shared item.
  • When you complete-split an item, split its dependents too. A role that exists only in development must take its dependent config with it, or import fails on the other environments.

Takeaway

Config Split is a scalpel for "what config exists in this environment." Drive it by hand-editing the split lists and verifying with cim; keep cex away from an active split; and route per-environment values through settings.php, not the split. Get that separation right and config-as-code stays trustworthy across every environment.