diff --git a/core/core.services.yml b/core/core.services.yml
index 1cddf59cfed553c7531e579591fb53d839bfb7db..e7378c6abf116fa02aeb909b96319dffbc238114 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -315,9 +315,16 @@ services:
     public: false
     tags:
       - { name: backend_overridable }
+  config.import_transformer:
+    class: Drupal\Core\Config\ImportStorageTransformer
+    arguments: ['@event_dispatcher', '@database', '@lock', '@lock.persistent']
   config.storage.export:
-    class: Drupal\Core\Config\ReadOnlyStorage
-    arguments: ['@config.storage']
+    class: Drupal\Core\Config\ManagedStorage
+    arguments: ['@config.storage.export.manager']
+  config.storage.export.manager:
+    class: Drupal\Core\Config\ExportStorageManager
+    arguments: ['@config.storage', '@database', '@event_dispatcher', '@lock']
+    public: false
   # @deprecated in Drupal 8.0.x and will be removed before 9.0.0. Use
   #   config.storage.sync instead.
   # @see https://www.drupal.org/node/2574957
diff --git a/core/lib/Drupal/Core/Config/ConfigEvents.php b/core/lib/Drupal/Core/Config/ConfigEvents.php
index 2aec6cbf440d5414452c6be43da569b3738fa65a..7686197d4ee217698906eb9bd2e3af1eb1a50d85 100644
--- a/core/lib/Drupal/Core/Config/ConfigEvents.php
+++ b/core/lib/Drupal/Core/Config/ConfigEvents.php
@@ -143,4 +143,64 @@ final class ConfigEvents {
    */
   const COLLECTION_INFO = 'config.collection_info';
 
+  /**
+   * Name of the event fired just before importing configuration.
+   *
+   * This event allows subscribers to modify the configuration which is about to
+   * be imported. The event listener method receives a
+   * \Drupal\Core\Config\StorageTransformEvent instance. This event contains a
+   * config storage which subscribers can interact with and which will finally
+   * be used to import the configuration from.
+   * Together with \Drupal\Core\Config\ConfigEvents::STORAGE_TRANSFORM_EXPORT
+   * subscribers can alter the active configuration in a config sync workflow
+   * instead of just overriding at runtime via the config-override system.
+   * This allows a complete customisation of the workflow including additional
+   * modules and editable configuration in different environments.
+   *
+   * @code
+   *   $storage = $event->getStorage();
+   * @endcode
+   *
+   * This event is also fired when just viewing the difference of configuration
+   * to be imported independently of whether the import takes place or not.
+   * Use the \Drupal\Core\Config\ConfigEvents::IMPORT event to subscribe to the
+   * import having taken place.
+   *
+   * @Event
+   *
+   * @see \Drupal\Core\Config\StorageTransformEvent
+   * @see \Drupal\Core\Config\ConfigEvents::STORAGE_TRANSFORM_EXPORT
+   * @see \Drupal\Core\Config\ImportStorageTransformer::transform
+   *
+   * @var string
+   */
+  const STORAGE_TRANSFORM_IMPORT = 'config.transform.import';
+
+  /**
+   * Name of the event fired when the export storage is used.
+   *
+   * This event allows subscribers to modify the configuration which is about to
+   * be exported. The event listener method receives a
+   * \Drupal\Core\Config\StorageTransformEvent instance. This event contains a
+   * config storage which subscribers can interact with and which will finally
+   * be used to export the configuration from.
+   *
+   * @code
+   *   $storage = $event->getStorage();
+   * @endcode
+   *
+   * Typically subscribers will want to perform the reverse operation on the
+   * storage than for \Drupal\Core\Config\ConfigEvents::STORAGE_TRANSFORM_IMPORT
+   * to make sure successive exports and imports yield no difference.
+   *
+   * @Event
+   *
+   * @see \Drupal\Core\Config\StorageTransformEvent
+   * @see \Drupal\Core\Config\ConfigEvents::STORAGE_TRANSFORM_IMPORT
+   * @see \Drupal\Core\Config\ExportStorageManager::getStorage
+   *
+   * @var string
+   */
+  const STORAGE_TRANSFORM_EXPORT = 'config.transform.export';
+
 }
diff --git a/core/modules/config_environment/src/Core/Config/ExportStorageManager.php b/core/lib/Drupal/Core/Config/ExportStorageManager.php
similarity index 78%
rename from core/modules/config_environment/src/Core/Config/ExportStorageManager.php
rename to core/lib/Drupal/Core/Config/ExportStorageManager.php
index f38b96585b1b251ce7ebdf55f9bbf494a4ec69be..99c3f1fd15ede1e83157b8497482e34e2b11cf7e 100644
--- a/core/modules/config_environment/src/Core/Config/ExportStorageManager.php
+++ b/core/lib/Drupal/Core/Config/ExportStorageManager.php
@@ -1,15 +1,7 @@
 <?php
 
-// @codingStandardsIgnoreStart
-// @todo: Move this back to \Drupal\Core\Config in #2991683.
-// Use this class with its class alias Drupal\Core\Config\ExportStorageManager
-// @codingStandardsIgnoreEnd
-namespace Drupal\config_environment\Core\Config;
+namespace Drupal\Core\Config;
 
-use Drupal\Core\Config\DatabaseStorage;
-use Drupal\Core\Config\ReadOnlyStorage;
-use Drupal\Core\Config\StorageCopyTrait;
-use Drupal\Core\Config\StorageInterface;
 use Drupal\Core\Database\Connection;
 use Drupal\Core\Lock\LockBackendInterface;
 use Symfony\Component\EventDispatcher\EventDispatcherInterface;
@@ -17,9 +9,11 @@
 /**
  * The export storage manager dispatches an event for the export storage.
  *
- * @internal
+ * This class is not meant to be extended and is final to make sure the
+ * constructor and the getStorage method are both changed when this pattern is
+ * used in other circumstances.
  */
-class ExportStorageManager implements StorageManagerInterface {
+final class ExportStorageManager implements StorageManagerInterface {
 
   use StorageCopyTrait;
 
@@ -91,8 +85,7 @@ public function getStorage() {
     }
 
     self::replaceStorageContents($this->active, $this->storage);
-    // @todo: Use ConfigEvents::STORAGE_TRANSFORM_EXPORT in #2991683
-    $this->eventDispatcher->dispatch('config.transform.export', new StorageTransformEvent($this->storage));
+    $this->eventDispatcher->dispatch(ConfigEvents::STORAGE_TRANSFORM_EXPORT, new StorageTransformEvent($this->storage));
 
     return new ReadOnlyStorage($this->storage);
   }
diff --git a/core/modules/config_environment/src/Core/Config/ImportStorageTransformer.php b/core/lib/Drupal/Core/Config/ImportStorageTransformer.php
similarity index 85%
rename from core/modules/config_environment/src/Core/Config/ImportStorageTransformer.php
rename to core/lib/Drupal/Core/Config/ImportStorageTransformer.php
index aa2983c9c0390b6d1e05088d61838888b5ddb336..58fe795dd4e7dad0bd02316f5cb03611abd37fba 100644
--- a/core/modules/config_environment/src/Core/Config/ImportStorageTransformer.php
+++ b/core/lib/Drupal/Core/Config/ImportStorageTransformer.php
@@ -1,25 +1,20 @@
 <?php
 
-// @codingStandardsIgnoreStart
-// @todo: Move this back to \Drupal\Core\Config in #2991683.
-// Use this class with its class alias Drupal\Core\Config\ImportStorageTransformer
-// @codingStandardsIgnoreEnd
-namespace Drupal\config_environment\Core\Config;
+namespace Drupal\Core\Config;
 
-use Drupal\Core\Config\ConfigImporter;
 use Drupal\Core\Database\Connection;
 use Drupal\Core\Lock\LockBackendInterface;
 use Symfony\Component\EventDispatcher\EventDispatcherInterface;
-use Drupal\Core\Config\DatabaseStorage;
-use Drupal\Core\Config\StorageCopyTrait;
-use Drupal\Core\Config\StorageInterface;
 
 /**
- * Class ImportStorageTransformer.
+ * The import storage transformer helps to use the configuration management api.
  *
- * @internal
+ * This service does not implement an interface and is final because it is not
+ * meant to be replaced, extended or used in a different context.
+ * Its single purpose is to transform a storage for the import step of a
+ * configuration synchronisation by dispatching the import transformation event.
  */
-class ImportStorageTransformer {
+final class ImportStorageTransformer {
 
   use StorageCopyTrait;
 
@@ -122,8 +117,7 @@ public function transform(StorageInterface $storage) {
     self::replaceStorageContents($storage, $mutable);
 
     // Dispatch the event so that event listeners can alter the configuration.
-    // @todo: Use ConfigEvents::STORAGE_TRANSFORM_IMPORT in #2991683
-    $this->eventDispatcher->dispatch('config.transform.import', new StorageTransformEvent($mutable));
+    $this->eventDispatcher->dispatch(ConfigEvents::STORAGE_TRANSFORM_IMPORT, new StorageTransformEvent($mutable));
 
     // Return the storage with the altered configuration.
     return $mutable;
diff --git a/core/modules/config_environment/src/Core/Config/ManagedStorage.php b/core/lib/Drupal/Core/Config/ManagedStorage.php
similarity index 90%
rename from core/modules/config_environment/src/Core/Config/ManagedStorage.php
rename to core/lib/Drupal/Core/Config/ManagedStorage.php
index 24f7eb52f98f0f941e0c53856ec479f49a19eed3..ef7649055fa1a184e09b3e7967211cd8e5b970e4 100644
--- a/core/modules/config_environment/src/Core/Config/ManagedStorage.php
+++ b/core/lib/Drupal/Core/Config/ManagedStorage.php
@@ -1,12 +1,6 @@
 <?php
 
-// @codingStandardsIgnoreStart
-// @todo: Move this back to \Drupal\Core\Config in #2991683.
-// Use this class with its class alias Drupal\Core\Config\ManagedStorage
-// @codingStandardsIgnoreEnd
-namespace Drupal\config_environment\Core\Config;
-
-use Drupal\Core\Config\StorageInterface;
+namespace Drupal\Core\Config;
 
 /**
  * The managed storage defers all the storage method calls to the manager.
@@ -16,9 +10,10 @@
  * the storage can be used so we can't do it in the constructor but we also
  * don't know which method is called first.
  *
- * @internal
+ * This class is not meant to be extended and is final to make sure the
+ * assumptions that the storage is retrieved only once are upheld.
  */
-class ManagedStorage implements StorageInterface {
+final class ManagedStorage implements StorageInterface {
 
   /**
    * The decorated storage.
diff --git a/core/modules/config_environment/src/Core/Config/StorageManagerInterface.php b/core/lib/Drupal/Core/Config/StorageManagerInterface.php
similarity index 57%
rename from core/modules/config_environment/src/Core/Config/StorageManagerInterface.php
rename to core/lib/Drupal/Core/Config/StorageManagerInterface.php
index 38943f8bb4b1118c6a0d1c3687de04e71909b807..677912048f1f12924748632752fde4b1e6d0b29d 100644
--- a/core/modules/config_environment/src/Core/Config/StorageManagerInterface.php
+++ b/core/lib/Drupal/Core/Config/StorageManagerInterface.php
@@ -1,15 +1,9 @@
 <?php
 
-// @codingStandardsIgnoreStart
-// @todo: Move this back to \Drupal\Core\Config in #2991683.
-// Use this class with its class alias Drupal\Core\Config\StorageManagerInterface
-// @codingStandardsIgnoreEnd
-namespace Drupal\config_environment\Core\Config;
+namespace Drupal\Core\Config;
 
 /**
  * Interface for a storage manager.
- *
- * @internal
  */
 interface StorageManagerInterface {
 
diff --git a/core/modules/config_environment/src/Core/Config/StorageTransformEvent.php b/core/lib/Drupal/Core/Config/StorageTransformEvent.php
similarity index 74%
rename from core/modules/config_environment/src/Core/Config/StorageTransformEvent.php
rename to core/lib/Drupal/Core/Config/StorageTransformEvent.php
index e0bc29cbfa66d11ff171ce0b370f17094c63d693..78951c4849e94b2b7d44b4895e1001454080b020 100644
--- a/core/modules/config_environment/src/Core/Config/StorageTransformEvent.php
+++ b/core/lib/Drupal/Core/Config/StorageTransformEvent.php
@@ -1,14 +1,8 @@
 <?php
 
-// @codingStandardsIgnoreStart
-// @todo: Move this back to \Drupal\Core\Config in #2991683.
-// Use this class with its class alias Drupal\Core\Config\StorageTransformEvent
-// @codingStandardsIgnoreEnd
-namespace Drupal\config_environment\Core\Config;
+namespace Drupal\Core\Config;
 
 use Symfony\Component\EventDispatcher\Event;
-// @todo: below removed when namespace is \Drupal\Core\Config in 2991683.
-use Drupal\Core\Config\StorageInterface;
 
 /**
  * Class StorageTransformEvent.
diff --git a/core/modules/config_environment/src/Core/Config/StorageTransformerException.php b/core/lib/Drupal/Core/Config/StorageTransformerException.php
similarity index 83%
rename from core/modules/config_environment/src/Core/Config/StorageTransformerException.php
rename to core/lib/Drupal/Core/Config/StorageTransformerException.php
index 747f6d8b525d55f341151ea2cf0828a690e471fb..3669e18d10c2620b67ccd118ae47d5d420beedb2 100644
--- a/core/modules/config_environment/src/Core/Config/StorageTransformerException.php
+++ b/core/lib/Drupal/Core/Config/StorageTransformerException.php
@@ -1,6 +1,6 @@
 <?php
 
-namespace Drupal\config_environment\Core\Config;
+namespace Drupal\Core\Config;
 
 /**
  * Thrown by config storage transformers if they cannot acquire a lock.
diff --git a/core/modules/config/src/Controller/ConfigController.php b/core/modules/config/src/Controller/ConfigController.php
index a4dc4ca07932e077019d4a7413e55e0c39c2007f..78f2ce80f8914842c6a211f697521b3127d75a85 100644
--- a/core/modules/config/src/Controller/ConfigController.php
+++ b/core/modules/config/src/Controller/ConfigController.php
@@ -4,6 +4,7 @@
 
 use Drupal\Core\Archiver\ArchiveTar;
 use Drupal\Core\Config\ConfigManagerInterface;
+use Drupal\Core\Config\ImportStorageTransformer;
 use Drupal\Core\Config\StorageInterface;
 use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
 use Drupal\Core\Diff\DiffFormatter;
@@ -28,11 +29,18 @@ class ConfigController implements ContainerInjectionInterface {
   protected $targetStorage;
 
   /**
-   * The source storage.
+   * The sync storage.
    *
    * @var \Drupal\Core\Config\StorageInterface
    */
-  protected $sourceStorage;
+  protected $syncStorage;
+
+  /**
+   * The import transformer service.
+   *
+   * @var \Drupal\Core\Config\ImportStorageTransformer
+   */
+  protected $importTransformer;
 
   /**
    * The configuration manager.
@@ -80,7 +88,8 @@ public static function create(ContainerInterface $container) {
       FileDownloadController::create($container),
       $container->get('diff.formatter'),
       $container->get('file_system'),
-      $container->get('config.storage.export')
+      $container->get('config.storage.export'),
+      $container->get('config.import_transformer')
     );
   }
 
@@ -89,8 +98,8 @@ public static function create(ContainerInterface $container) {
    *
    * @param \Drupal\Core\Config\StorageInterface $target_storage
    *   The target storage.
-   * @param \Drupal\Core\Config\StorageInterface $source_storage
-   *   The source storage.
+   * @param \Drupal\Core\Config\StorageInterface $sync_storage
+   *   The sync storage.
    * @param \Drupal\Core\Config\ConfigManagerInterface $config_manager
    *   The config manager.
    * @param \Drupal\system\FileDownloadController $file_download_controller
@@ -101,10 +110,12 @@ public static function create(ContainerInterface $container) {
    *   The file system.
    * @param \Drupal\Core\Config\StorageInterface $export_storage
    *   The export storage.
+   * @param \Drupal\Core\Config\ImportStorageTransformer $import_transformer
+   *   The import transformer service.
    */
-  public function __construct(StorageInterface $target_storage, StorageInterface $source_storage, ConfigManagerInterface $config_manager, FileDownloadController $file_download_controller, DiffFormatter $diff_formatter, FileSystemInterface $file_system, StorageInterface $export_storage = NULL) {
+  public function __construct(StorageInterface $target_storage, StorageInterface $sync_storage, ConfigManagerInterface $config_manager, FileDownloadController $file_download_controller, DiffFormatter $diff_formatter, FileSystemInterface $file_system, StorageInterface $export_storage = NULL, ImportStorageTransformer $import_transformer = NULL) {
     $this->targetStorage = $target_storage;
-    $this->sourceStorage = $source_storage;
+    $this->syncStorage = $sync_storage;
     $this->configManager = $config_manager;
     $this->fileDownloadController = $file_download_controller;
     $this->diffFormatter = $diff_formatter;
@@ -114,6 +125,11 @@ public function __construct(StorageInterface $target_storage, StorageInterface $
       $export_storage = \Drupal::service('config.storage.export');
     }
     $this->exportStorage = $export_storage;
+    if (is_null($import_transformer)) {
+      @trigger_error('The config.import_transformer service must be passed to ConfigController::__construct(), it is required before Drupal 9.0.0. See https://www.drupal.org/node/3066005.', E_USER_DEPRECATED);
+      $import_transformer = \Drupal::service('config.import_transformer');
+    }
+    $this->importTransformer = $import_transformer;
   }
 
   /**
@@ -163,7 +179,8 @@ public function diff($source_name, $target_name = NULL, $collection = NULL) {
     if (!isset($collection)) {
       $collection = StorageInterface::DEFAULT_COLLECTION;
     }
-    $diff = $this->configManager->diff($this->targetStorage, $this->sourceStorage, $source_name, $target_name, $collection);
+    $syncStorage = $this->importTransformer->transform($this->syncStorage);
+    $diff = $this->configManager->diff($this->targetStorage, $syncStorage, $source_name, $target_name, $collection);
     $this->diffFormatter->show_header = FALSE;
 
     $build = [];
diff --git a/core/modules/config/src/Form/ConfigSync.php b/core/modules/config/src/Form/ConfigSync.php
index ccbbbe9a775bca3bb5ba45f9f925dda4a119da50..37c6218aaf0c70e9b8cdbf3d0675f8002bda1387 100644
--- a/core/modules/config/src/Form/ConfigSync.php
+++ b/core/modules/config/src/Form/ConfigSync.php
@@ -5,6 +5,7 @@
 use Drupal\Core\Config\ConfigImporterException;
 use Drupal\Core\Config\ConfigImporter;
 use Drupal\Core\Config\Importer\ConfigImporterBatch;
+use Drupal\Core\Config\ImportStorageTransformer;
 use Drupal\Core\Config\TypedConfigManagerInterface;
 use Drupal\Core\Extension\ModuleExtensionList;
 use Drupal\Core\Extension\ModuleHandlerInterface;
@@ -112,6 +113,13 @@ class ConfigSync extends FormBase {
    */
   protected $moduleExtensionList;
 
+  /**
+   * The import transformer service.
+   *
+   * @var \Drupal\Core\Config\ImportStorageTransformer
+   */
+  protected $importTransformer;
+
   /**
    * Constructs the object.
    *
@@ -139,8 +147,10 @@ class ConfigSync extends FormBase {
    *   The renderer.
    * @param \Drupal\Core\Extension\ModuleExtensionList $extension_list_module
    *   The module extension list
+   * @param \Drupal\Core\Config\ImportStorageTransformer $import_transformer
+   *   The import transformer service.
    */
-  public function __construct(StorageInterface $sync_storage, StorageInterface $active_storage, StorageInterface $snapshot_storage, LockBackendInterface $lock, EventDispatcherInterface $event_dispatcher, ConfigManagerInterface $config_manager, TypedConfigManagerInterface $typed_config, ModuleHandlerInterface $module_handler, ModuleInstallerInterface $module_installer, ThemeHandlerInterface $theme_handler, RendererInterface $renderer, ModuleExtensionList $extension_list_module) {
+  public function __construct(StorageInterface $sync_storage, StorageInterface $active_storage, StorageInterface $snapshot_storage, LockBackendInterface $lock, EventDispatcherInterface $event_dispatcher, ConfigManagerInterface $config_manager, TypedConfigManagerInterface $typed_config, ModuleHandlerInterface $module_handler, ModuleInstallerInterface $module_installer, ThemeHandlerInterface $theme_handler, RendererInterface $renderer, ModuleExtensionList $extension_list_module, ImportStorageTransformer $import_transformer = NULL) {
     $this->syncStorage = $sync_storage;
     $this->activeStorage = $active_storage;
     $this->snapshotStorage = $snapshot_storage;
@@ -153,6 +163,11 @@ public function __construct(StorageInterface $sync_storage, StorageInterface $ac
     $this->themeHandler = $theme_handler;
     $this->renderer = $renderer;
     $this->moduleExtensionList = $extension_list_module;
+    if (is_null($import_transformer)) {
+      @trigger_error('The config.import_transformer service must be passed to ConfigSync::__construct(), it is required before Drupal 9.0.0. See https://www.drupal.org/node/3066005.', E_USER_DEPRECATED);
+      $import_transformer = \Drupal::service('config.import_transformer');
+    }
+    $this->importTransformer = $import_transformer;
   }
 
   /**
@@ -171,7 +186,8 @@ public static function create(ContainerInterface $container) {
       $container->get('module_installer'),
       $container->get('theme_handler'),
       $container->get('renderer'),
-      $container->get('extension.list.module')
+      $container->get('extension.list.module'),
+      $container->get('config.import_transformer')
     );
   }
 
@@ -191,8 +207,9 @@ public function buildForm(array $form, FormStateInterface $form_state) {
       '#type' => 'submit',
       '#value' => $this->t('Import all'),
     ];
-    $source_list = $this->syncStorage->listAll();
-    $storage_comparer = new StorageComparer($this->syncStorage, $this->activeStorage);
+    $syncStorage = $this->importTransformer->transform($this->syncStorage);
+    $source_list = $syncStorage->listAll();
+    $storage_comparer = new StorageComparer($syncStorage, $this->activeStorage);
     if (empty($source_list) || !$storage_comparer->createChangelist()->hasChanges()) {
       $form['no_changes'] = [
         '#type' => 'table',
diff --git a/core/modules/config/tests/config_transformer_test/config_transformer_test.info.yml b/core/modules/config/tests/config_transformer_test/config_transformer_test.info.yml
new file mode 100644
index 0000000000000000000000000000000000000000..6fb64de9e8051545cf4eee3f047cf1189dc91e1b
--- /dev/null
+++ b/core/modules/config/tests/config_transformer_test/config_transformer_test.info.yml
@@ -0,0 +1,7 @@
+name: 'Configuration Storage Transformer Test'
+type: module
+package: Testing
+version: VERSION
+core: 8.x
+dependencies:
+  - drupal:config
diff --git a/core/modules/config_environment/tests/config_transformer_test/config_transformer_test.services.yml b/core/modules/config/tests/config_transformer_test/config_transformer_test.services.yml
similarity index 100%
rename from core/modules/config_environment/tests/config_transformer_test/config_transformer_test.services.yml
rename to core/modules/config/tests/config_transformer_test/config_transformer_test.services.yml
diff --git a/core/modules/config_environment/tests/config_transformer_test/src/EventSubscriber.php b/core/modules/config/tests/config_transformer_test/src/EventSubscriber.php
similarity index 94%
rename from core/modules/config_environment/tests/config_transformer_test/src/EventSubscriber.php
rename to core/modules/config/tests/config_transformer_test/src/EventSubscriber.php
index ebaef02c2a0bb5dff44e971074f136b13c220711..1370020abd589a549c1fb684bbdaa3ff2ff5a935 100644
--- a/core/modules/config_environment/tests/config_transformer_test/src/EventSubscriber.php
+++ b/core/modules/config/tests/config_transformer_test/src/EventSubscriber.php
@@ -2,6 +2,7 @@
 
 namespace Drupal\config_transformer_test;
 
+use Drupal\Core\Config\ConfigEvents;
 use Drupal\Core\Config\StorageInterface;
 use Drupal\Core\Config\StorageTransformEvent;
 use Drupal\Core\State\StateInterface;
@@ -105,9 +106,8 @@ public function onExportTransform(StorageTransformEvent $event) {
    * {@inheritdoc}
    */
   public static function getSubscribedEvents() {
-    // @todo: use class constants when they get added in #2991683
-    $events['config.transform.import'][] = ['onImportTransform'];
-    $events['config.transform.export'][] = ['onExportTransform'];
+    $events[ConfigEvents::STORAGE_TRANSFORM_IMPORT][] = ['onImportTransform'];
+    $events[ConfigEvents::STORAGE_TRANSFORM_EXPORT][] = ['onExportTransform'];
     return $events;
   }
 
diff --git a/core/modules/config_environment/tests/src/Functional/TransformedConfigExportImportUITest.php b/core/modules/config/tests/src/Functional/TransformedConfigExportImportUITest.php
similarity index 94%
rename from core/modules/config_environment/tests/src/Functional/TransformedConfigExportImportUITest.php
rename to core/modules/config/tests/src/Functional/TransformedConfigExportImportUITest.php
index 6de7b7fbb3d3645a4761a9d1b9f85fc5a8ca4c92..b87d12a16dc4cceac5b872ccbc33e6f418cb606a 100644
--- a/core/modules/config_environment/tests/src/Functional/TransformedConfigExportImportUITest.php
+++ b/core/modules/config/tests/src/Functional/TransformedConfigExportImportUITest.php
@@ -1,9 +1,6 @@
 <?php
 
-// @codingStandardsIgnoreStart
-// @todo: Move this back to \Drupal\Tests\config\Functional in #2991683.
-// @codingStandardsIgnoreEnd
-namespace Drupal\Tests\config_environment\Functional;
+namespace Drupal\Tests\config\Functional;
 
 use Drupal\Component\Utility\Html;
 use Drupal\Tests\BrowserTestBase;
@@ -21,7 +18,6 @@ class TransformedConfigExportImportUITest extends BrowserTestBase {
   public static $modules = [
     'config',
     'config_transformer_test',
-    'config_environment',
   ];
 
   /**
diff --git a/core/modules/config_environment/config_environment.module b/core/modules/config_environment/config_environment.module
index a5f2892c0bb9e6682b5c8655632f383c6f7e6579..b54b3dc632f16321d8de442d3e5fb881f913b430 100644
--- a/core/modules/config_environment/config_environment.module
+++ b/core/modules/config_environment/config_environment.module
@@ -5,16 +5,6 @@
  * Allows site administrators to modify environment configuration.
  */
 
-// Set class aliases for the classes that will go into core when we are in beta.
-// See the experimental modules policy https://www.drupal.org/core/experimental
-// @todo: remove class aliases in #2991683
-@class_alias('Drupal\config_environment\Core\Config\StorageTransformEvent', 'Drupal\Core\Config\StorageTransformEvent');
-@class_alias('Drupal\config_environment\Core\Config\ManagedStorage', 'Drupal\Core\Config\ManagedStorage');
-@class_alias('Drupal\config_environment\Core\Config\StorageManagerInterface', 'Drupal\Core\Config\StorageManagerInterface');
-@class_alias('Drupal\config_environment\Core\Config\ExportStorageManager', 'Drupal\Core\Config\ExportStorageManager');
-@class_alias('Drupal\config_environment\Core\Config\ImportStorageTransformer', 'Drupal\Core\Config\ImportStorageTransformer');
-@class_alias('Drupal\config_environment\Core\Config\StorageTransformerException', 'Drupal\Core\Config\StorageTransformerException');
-
 use Drupal\Core\Routing\RouteMatchInterface;
 
 /**
diff --git a/core/modules/config_environment/config_environment.routing.yml b/core/modules/config_environment/config_environment.routing.yml
deleted file mode 100644
index 7c9edeac212649776f2d16a82fd81c0cd8c7685b..0000000000000000000000000000000000000000
--- a/core/modules/config_environment/config_environment.routing.yml
+++ /dev/null
@@ -1,31 +0,0 @@
-# @todo: Stop taking over config module routes in #2991683
-config.sync:
-  path: '/admin/config/development/configuration'
-  defaults:
-    _form: '\Drupal\config_environment\Form\ConfigSync'
-    _title: 'Synchronize'
-  requirements:
-    _permission: 'synchronize configuration'
-
-config.diff:
-  path: '/admin/config/development/configuration/sync/diff/{source_name}/{target_name}'
-  defaults:
-    _controller: '\Drupal\config_environment\Controller\ConfigController::diff'
-    target_name: NULL
-  requirements:
-    _permission: 'synchronize configuration'
-
-config.diff_collection:
-  path: '/admin/config/development/configuration/sync/diff_collection/{collection}/{source_name}/{target_name}'
-  defaults:
-    _controller: '\Drupal\config_environment\Controller\ConfigController::diff'
-    target_name: NULL
-  requirements:
-    _permission: 'synchronize configuration'
-
-config.export_download:
-  path: '/admin/config/development/configuration/full/export-download'
-  defaults:
-    _controller: '\Drupal\config_environment\Controller\ConfigController::downloadExport'
-  requirements:
-    _permission: 'export configuration'
diff --git a/core/modules/config_environment/config_environment.services.yml b/core/modules/config_environment/config_environment.services.yml
index 3c9482a9dfceb6a5634b48e905f4ce77288df20b..857f3eda8c6da924fa2fa348fe206726830478ff 100644
--- a/core/modules/config_environment/config_environment.services.yml
+++ b/core/modules/config_environment/config_environment.services.yml
@@ -1,15 +1,4 @@
 services:
-  # @todo: Move this back to core services in #2991683
-  config.import_transformer:
-    class: Drupal\config_environment\Core\Config\ImportStorageTransformer
-    arguments: ['@event_dispatcher', '@database', '@lock', '@lock.persistent']
-  config.storage.export:
-    class: Drupal\config_environment\Core\Config\ManagedStorage
-    arguments: ['@config.storage.export.manager']
-  config.storage.export.manager:
-    class: Drupal\config_environment\Core\Config\ExportStorageManager
-    arguments: ['@config.storage', '@database', '@event_dispatcher', '@lock']
-  # config_environment services.
   config_environment.excluded_modules.event_subscriber:
     class: Drupal\config_environment\EventSubscriber\ExcludedModulesEventSubscriber
     arguments: ['@config.storage', '@settings', '@config.manager']
diff --git a/core/modules/config_environment/src/Controller/ConfigController.php b/core/modules/config_environment/src/Controller/ConfigController.php
deleted file mode 100644
index 92cb3fa9a612bb972d6da35885ccd5b074aca874..0000000000000000000000000000000000000000
--- a/core/modules/config_environment/src/Controller/ConfigController.php
+++ /dev/null
@@ -1,47 +0,0 @@
-<?php
-
-namespace Drupal\config_environment\Controller;
-
-use Drupal\config\Controller\ConfigController as OriginalConfigController;
-use Symfony\Component\DependencyInjection\ContainerInterface;
-
-/**
- * Returns responses for config module routes.
- */
-class ConfigController extends OriginalConfigController {
-
-  /**
-   * The import transformer service.
-   *
-   * @var \Drupal\Core\Config\ImportStorageTransformer
-   */
-  protected $importTransformer;
-
-  /**
-   * The sync storage.
-   *
-   * @var \Drupal\Core\Config\StorageInterface
-   */
-  protected $syncStorage;
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function create(ContainerInterface $container) {
-    $controller = parent::create($container);
-    $controller->importTransformer = $container->get('config.import_transformer');
-    $controller->syncStorage = $container->get('config.storage.sync');
-
-    return $controller;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function diff($source_name, $target_name = NULL, $collection = NULL) {
-    $this->sourceStorage = $this->importTransformer->transform($this->syncStorage);
-
-    return parent::diff($source_name, $target_name, $collection);
-  }
-
-}
diff --git a/core/modules/config_environment/src/Core/Config/ConfigEvents.php b/core/modules/config_environment/src/Core/Config/ConfigEvents.php
deleted file mode 100644
index c10056554a26b1e654602ea4a3b999b022a8cb48..0000000000000000000000000000000000000000
--- a/core/modules/config_environment/src/Core/Config/ConfigEvents.php
+++ /dev/null
@@ -1,81 +0,0 @@
-<?php
-
-// @codingStandardsIgnoreStart
-// @todo: Move this back to \Drupal\Core\Config\ConfigEvents in #2991683.
-// @codingStandardsIgnoreEnd
-namespace Drupal\config_environment\Core\Config;
-
-/**
- * Defines events for the configuration transform system.
- *
- * The constants in this class will be moved back into ConfigEvents.
- * But due to the fact that the config_environment is not in beta we save their
- * definitions here and use the literal strings in the mean time.
- *
- * @internal
- *
- * @deprecated The class will be merged with Drupal\Core\Config\ConfigEvents.
- */
-final class ConfigEvents {
-
-  /**
-   * Name of the event fired just before importing configuration.
-   *
-   * This event allows subscribers to modify the configuration which is about to
-   * be imported. The event listener method receives a
-   * \Drupal\Core\Config\StorageTransformEvent instance. This event contains a
-   * config storage which subscribers can interact with and which will finally
-   * be used to import the configuration from.
-   * Together with \Drupal\Core\Config\ConfigEvents::STORAGE_TRANSFORM_EXPORT
-   * subscribers can alter the active configuration in a config sync workflow
-   * instead of just overriding at runtime via the config-override system.
-   * This allows a complete customisation of the workflow including additional
-   * modules and editable configuration in different environments.
-   *
-   * @code
-   *   $storage = $event->getStorage();
-   * @endcode
-   *
-   * This event is also fired when just viewing the difference of configuration
-   * to be imported independently of whether the import takes place or not.
-   * Use the \Drupal\Core\Config\ConfigEvents::IMPORT event to subscribe to the
-   * import having taken place.
-   *
-   * @Event
-   *
-   * @see \Drupal\Core\Config\StorageTransformEvent
-   * @see \Drupal\Core\Config\ConfigEvents::STORAGE_TRANSFORM_EXPORT
-   * @see \Drupal\Core\Config\ImportStorageTransformer::transform
-   *
-   * @var string
-   */
-  const STORAGE_TRANSFORM_IMPORT = 'config.transform.import';
-
-  /**
-   * Name of the event fired when the export storage is used.
-   *
-   * This event allows subscribers to modify the configuration which is about to
-   * be exported. The event listener method receives a
-   * \Drupal\Core\Config\StorageTransformEvent instance. This event contains a
-   * config storage which subscribers can interact with and which will finally
-   * be used to export the configuration from.
-   *
-   * @code
-   *   $storage = $event->getStorage();
-   * @endcode
-   *
-   * Typically subscribers will want to perform the reverse operation on the
-   * storage than for \Drupal\Core\Config\ConfigEvents::STORAGE_TRANSFORM_IMPORT
-   * to make sure successive exports and imports yield no difference.
-   *
-   * @Event
-   *
-   * @see \Drupal\Core\Config\StorageTransformEvent
-   * @see \Drupal\Core\Config\ConfigEvents::STORAGE_TRANSFORM_IMPORT
-   * @see \Drupal\config_environment\Core\Config\ExportStorageManager::getStorage
-   *
-   * @var string
-   */
-  const STORAGE_TRANSFORM_EXPORT = 'config.transform.export';
-
-}
diff --git a/core/modules/config_environment/src/Form/ConfigSync.php b/core/modules/config_environment/src/Form/ConfigSync.php
deleted file mode 100644
index 47b04c0ad5cc6421f7cc46ac0add4b86a48fbbdc..0000000000000000000000000000000000000000
--- a/core/modules/config_environment/src/Form/ConfigSync.php
+++ /dev/null
@@ -1,48 +0,0 @@
-<?php
-
-namespace Drupal\config_environment\Form;
-
-use Drupal\config\Form\ConfigSync as OriginalConfigSync;
-use Drupal\Core\Form\FormStateInterface;
-use Symfony\Component\DependencyInjection\ContainerInterface;
-
-/**
- * Overrides the ConfigSync form.
- */
-class ConfigSync extends OriginalConfigSync {
-
-  /**
-   * The import transformer service.
-   *
-   * @var \Drupal\Core\Config\ImportStorageTransformer
-   */
-  protected $importTransformer;
-
-  /**
-   * The sync storage.
-   *
-   * @var \Drupal\Core\Config\StorageInterface
-   */
-  protected $originalSyncStorage;
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function create(ContainerInterface $container) {
-    $form = parent::create($container);
-    $form->importTransformer = $container->get('config.import_transformer');
-    $form->originalSyncStorage = $form->syncStorage;
-
-    return $form;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function buildForm(array $form, FormStateInterface $form_state) {
-    $this->syncStorage = $this->importTransformer->transform($this->originalSyncStorage);
-
-    return parent::buildForm($form, $form_state);
-  }
-
-}
diff --git a/core/modules/config_environment/tests/config_exclude_test/config_exclude_test.info.yml b/core/modules/config_environment/tests/config_exclude_test/config_exclude_test.info.yml
index 586a29d62abc1f6d04e2aeadbb0a5a7b33708d6d..6ee30864798c95931763c041b06a2b2ae7d03e07 100644
--- a/core/modules/config_environment/tests/config_exclude_test/config_exclude_test.info.yml
+++ b/core/modules/config_environment/tests/config_exclude_test/config_exclude_test.info.yml
@@ -1,4 +1,4 @@
-# @todo: Move this test module under the config module in #2991683.
+# @todo: Move this test module under the config module in #3079029.
 name: 'Configuration Module Exclude Test'
 type: module
 package: Testing
diff --git a/core/modules/config_environment/tests/config_transformer_test/config_transformer_test.info.yml b/core/modules/config_environment/tests/config_transformer_test/config_transformer_test.info.yml
deleted file mode 100644
index 3fbdd561a0a8bb173f8aff0296d1771fb89aab04..0000000000000000000000000000000000000000
--- a/core/modules/config_environment/tests/config_transformer_test/config_transformer_test.info.yml
+++ /dev/null
@@ -1,10 +0,0 @@
-# @todo: Move this test module under the config module in #2991683.
-name: 'Configuration Storage Transformer Test'
-type: module
-package: Testing
-version: VERSION
-core: 8.x
-dependencies:
-  - drupal:config
-# @todo: remove dependency on config_environment in #2991683.
-  - drupal:config_environment
diff --git a/core/modules/config_environment/tests/src/Kernel/EventSubscriber/ExcludedModulesEventSubscriberTest.php b/core/modules/config_environment/tests/src/Kernel/EventSubscriber/ExcludedModulesEventSubscriberTest.php
index e9c43fe936e97d5e6f9dc0bd30d76c436b9a98f4..8e7f0638fc65de9eedf8dcf0474bc72d7e813a0c 100644
--- a/core/modules/config_environment/tests/src/Kernel/EventSubscriber/ExcludedModulesEventSubscriberTest.php
+++ b/core/modules/config_environment/tests/src/Kernel/EventSubscriber/ExcludedModulesEventSubscriberTest.php
@@ -73,10 +73,14 @@ public function testExcludedModules() {
       $this->assertEquals($active->read($config), $import->read($config));
     }
 
-    // Changing the settings triggers the export storage manager to re-dispatch
-    // the events so the config_text will not be excluded.
+    // When the settings are changed, the next request will get the export
+    // storage without the config_test excluded.
     $this->setSetting('config_exclude_modules', []);
-    $export = $this->container->get('config.storage.export.manager')->getStorage();
+    // We rebuild the container to simulate a new request. The managed storage
+    // gets the storage from the manager only once.
+    $this->container->get('kernel')->rebuildContainer();
+    $export = $this->container->get('config.storage.export');
+
     $this->assertArrayHasKey('config_test', $export->read('core.extension')['module']);
   }
 
diff --git a/core/modules/config_environment/tests/src/Kernel/Core/Config/ExportStorageManagerTest.php b/core/tests/Drupal/KernelTests/Core/Config/ExportStorageManagerTest.php
similarity index 93%
rename from core/modules/config_environment/tests/src/Kernel/Core/Config/ExportStorageManagerTest.php
rename to core/tests/Drupal/KernelTests/Core/Config/ExportStorageManagerTest.php
index 30727daa23e9538396ca6e4d95685adea6ed781b..e76ff0421a5e936d0c70a41f6677eb5b3e7032d5 100644
--- a/core/modules/config_environment/tests/src/Kernel/Core/Config/ExportStorageManagerTest.php
+++ b/core/tests/Drupal/KernelTests/Core/Config/ExportStorageManagerTest.php
@@ -1,9 +1,6 @@
 <?php
 
-// @codingStandardsIgnoreStart
-// @todo: Move this back to \Drupal\KernelTests\Core\Config in #2991683.
-// @codingStandardsIgnoreEnd
-namespace Drupal\Tests\config_environment\Kernel\Core\Config;
+namespace Drupal\KernelTests\Core\Config;
 
 use Drupal\Core\Config\ExportStorageManager;
 use Drupal\Core\Config\StorageTransformerException;
@@ -23,7 +20,6 @@ class ExportStorageManagerTest extends KernelTestBase {
   protected static $modules = [
     'system',
     'config_transformer_test',
-    'config_environment',
   ];
 
   /**
diff --git a/core/modules/config_environment/tests/src/Kernel/Core/Config/ImportStorageTransformerTest.php b/core/tests/Drupal/KernelTests/Core/Config/ImportStorageTransformerTest.php
similarity index 94%
rename from core/modules/config_environment/tests/src/Kernel/Core/Config/ImportStorageTransformerTest.php
rename to core/tests/Drupal/KernelTests/Core/Config/ImportStorageTransformerTest.php
index d958c110487877bbf362cf2d949a7625626e304c..cb10d77c2cf22db6310af91852fe70e25de3b755 100644
--- a/core/modules/config_environment/tests/src/Kernel/Core/Config/ImportStorageTransformerTest.php
+++ b/core/tests/Drupal/KernelTests/Core/Config/ImportStorageTransformerTest.php
@@ -1,9 +1,6 @@
 <?php
 
-// @codingStandardsIgnoreStart
-// @todo: Move this back to \Drupal\KernelTests\Core\Config in #2991683.
-// @codingStandardsIgnoreEnd
-namespace Drupal\Tests\config_environment\Kernel\Core\Config;
+namespace Drupal\KernelTests\Core\Config;
 
 use Drupal\Core\Config\ConfigImporter;
 use Drupal\Core\Config\ImportStorageTransformer;
@@ -25,7 +22,6 @@ class ImportStorageTransformerTest extends KernelTestBase {
   protected static $modules = [
     'system',
     'config_transformer_test',
-    'config_environment',
   ];
 
   /**
diff --git a/core/modules/config_environment/tests/src/Kernel/Core/Config/Storage/ManagedStorageTest.php b/core/tests/Drupal/KernelTests/Core/Config/Storage/ManagedStorageTest.php
similarity index 77%
rename from core/modules/config_environment/tests/src/Kernel/Core/Config/Storage/ManagedStorageTest.php
rename to core/tests/Drupal/KernelTests/Core/Config/Storage/ManagedStorageTest.php
index 1b6ae9a72786232307af4b4d7e2c55159c707907..33932e36c5b695f4e3e555fc421aedfb1cb5cf5e 100644
--- a/core/modules/config_environment/tests/src/Kernel/Core/Config/Storage/ManagedStorageTest.php
+++ b/core/tests/Drupal/KernelTests/Core/Config/Storage/ManagedStorageTest.php
@@ -1,17 +1,10 @@
 <?php
 
-// @codingStandardsIgnoreStart
-// @todo: Move this back to \Drupal\KernelTests\Core\Config\Storage in #2991683.
-// @codingStandardsIgnoreEnd
-namespace Drupal\Tests\config_environment\Kernel\Core\Config\Storage;
-
-// include class aliases. @todo: remove in #2991683.
-include_once __DIR__ . '/../../../../../../config_environment.module';
+namespace Drupal\KernelTests\Core\Config\Storage;
 
 use Drupal\Core\Config\StorageManagerInterface;
 use Drupal\Core\Config\ManagedStorage;
 use Drupal\Core\Config\MemoryStorage;
-use Drupal\KernelTests\Core\Config\Storage\ConfigStorageTestBase;
 
 /**
  * Tests ManagedStorage operations.