Visualizing Drupal's Configuration Management Process

The configuration management system in Drupal allows for configuration to be imported and exported between the file system and the database. This enables the management of configuration with version control and allows configuration to be shared across environments (e.g. dev, staging, prod).

At its core it is quite simple, but modern website development workflows and processes can quickly lead to edge cases, which if not handled carefully, can trip up even the most experienced developer and will surely confuse anyone new to Drupal.

Key Concepts

Configuration Instances

There are two independent and complete instances of the configuration when using Drupal's default configuration tooling.

Note:There are exceptions to this as you begin adding modules such as config_ignore, config_split, etc to your workflow. It would be impossible to cover all of the possible permutations, however, if they are configured correctly, the complexity they introduce will likely be hidden in the day-to-day workflows described below.

Active Configuration

One instance of the configuration lives in the database. The database configuration is used when building pages and rendering data. This is essentially the only configuration Drupal knows about and is often referred to as the “active state.” The database configuration is altered when updating information within the admin UI, such as a change to the site name.

Codebase Configuration

The other instance of the configuration lives in a folder full of yml files within the codebase. The location of this folder is defined by $settings['config_sync_directory']. These files are typically tracked via version control and deployed with the codebase.

Configuration Syncing

The two instances are independent, but can be synced using the Drupal admin UI or via Drush commands.

  • Configuration import is the process of syncing the changes from the yml files into the database. This is often performed with drush config:import.
  • Configuration export is the process of syncing the changes from the database to the yml files in the codebase. This is often performed with drush config:export.

Configuration Gone Wrong

With a baseline understanding, let’s explore some common scenarios where improper management of the configuration has unwanted and destructive side-effects.

Example 1 - Deleted Files

Scenario: You submit your PR and it deletes configuration files. During code review, one of your colleagues asks, "Why is this configuration file being deleted?"

Initial state while working on example-branch.

Code Configuration

Config A
Config B

Active Configuration

Config A
Config B

The latest commits from the main branch are merged into example-branch.

Code Configuration

Config A
Config B
Config D

Active Configuration

Config A
Config B

Configuration is updated in the admin UI.

Code Configuration

Config A
Config B
Config D

Active Configuration

Config A
Config B
Config C

Configuration is exported and the local diff shows the deletion of configuration D.

Code Configuration

Config A
Config B
Config C

Active Configuration

Config A
Config B
Config C

What went wrong?

The active configuration was not synced with the code configuration when the configuration file D changes were merged in. When the latest commits from the main branch were merged into example-branch a configuration import should have been performed to ensure that the active configuration in the database precisely mirrors the configuration tracked in code.

Example 2 - Lost Configuration

Scenario: You are configuring a new feature in the Drupal UI and all of your work is wiped out.

Initial state while working on example-branch-one.

Code Configuration

Config A
Config B

Active Configuration

Config A
Config B

Configuration is updated in the admin UI.

Code Configuration

Config A
Config B

Active Configuration

Config A
Config B
Config C

Switch to example-branch-two to continue work on another issue.

Code Configuration

Config A
Config D

Active Configuration

Config A
Config B
Config C

Import configuration and discover that all of the work that went into making the C configuration changes was lost, and the B configuration is missing too.

Code Configuration

Config A
Config D

Active Configuration

Config A
Config D

What went wrong?

Configuration should have been exported before switching branches. It’s normally best to always export configuration and commit it to the current branch before moving on.

Example 3 - Extra Configuration Files

Scenario: You submit your PR and it includes a bunch of new configuration files. During code review, one of your colleagues asks, “Why is this unrelated configuration in this PR?"

Initial state while working on example-branch-one.

Code Configuration

Config A
Config B

Active Configuration

Config A
Config B

Switch to example-branch-two to continue work on another issue.

Code Configuration

Config A

Active Configuration

Config A
Config B

Additional configuration changes are made in the UI.

Code Configuration

Config A

Active Configuration

Config A
Config B
Config D

Configuration is exported and configuration B is included, but it is unrelated to the current work/branch.

Code Configuration

Config A
Config B
Config D

Active Configuration

Config A
Config B
Config D

What went wrong?

Configuration should have been imported after switching branches. This would have removed configuration B from the active configuration and prevented it from being exported.

Managing Configuration Correctly

Understanding the state of the two configuration instances and how they relate as the code and database change throughout the development process will greatly aid in reducing frustration and producing clean diffs for code review.

Initial state while working on example-branch-one.

Code Configuration

Config A

Active Configuration

Config A

Configuration is updated in the admin UI.

Code Configuration

Config A

Active Configuration

Config A
Config B

Configuration is exported to the file system and committed to example-branch-one.

Code Configuration

Config A
Config B

Active Configuration

Config A
Config B

Switch to example-branch-two to continue work on another issue.

Code Configuration

Config A
Config C

Active Configuration

Config A
Config B

Configuration is imported.

Code Configuration

Config A
Config C

Active Configuration

Config A
Config C

Additional configuration changes are made in the UI.

Code Configuration

Config A
Config C

Active Configuration

Config A
Config C
Config D

Configuration is exported. Only the expected configuration D is included in the diff, and configuration B is safely tracked in the example-branch-one branch.

Code Configuration

Config A
Config C
Config D

Active Configuration

Config A
Config C
Config D

Lessons Learned

Alway assume that the codebase configuration and database (active) configuration are not in sync after either of them change. Once the mindset of needing to keep the configuration files and the active configuration in sync is adopted, the habits of importing and exporting configuration begin to become second nature.

As someone who has done considerable work with configuration, writing this was a great exercise that still tripped me up a few times. Managing state is never easy in programming, especially when you mix version control in with it. However, hopefully these illustrations will help with visualizing the situation the next time you are trying to figure out what configuration is where and what it all means.