diff --git a/core/core.services.yml b/core/core.services.yml
index 8e203ed..1564692 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -38,13 +38,6 @@ services:
     factory_method: get
     factory_service: cache_factory
     arguments: [bootstrap]
-  cache.config:
-    class: Drupal\Core\Cache\CacheBackendInterface
-    tags:
-      - { name: cache.bin }
-    factory_method: get
-    factory_service: cache_factory
-    arguments: [config]
   cache.default:
     class: Drupal\Core\Cache\CacheBackendInterface
     tags:
@@ -115,7 +108,7 @@ services:
     class: Drupal\Core\Config\InstallStorage
   config.typed:
     class: Drupal\Core\Config\TypedConfigManager
-    arguments: ['@config.storage', '@config.storage.schema', '@cache.config']
+    arguments: ['@config.storage', '@config.storage.schema', '@cache.default']
   cron:
     class: Drupal\Core\Cron
     arguments: ['@module_handler', '@lock', '@queue', '@state', '@current_user', '@session_manager']
diff --git a/core/lib/Drupal/Core/Config/CachedStorage.php b/core/lib/Drupal/Core/Config/CachedStorage.php
index a5d11fd..9fe13db 100644
--- a/core/lib/Drupal/Core/Config/CachedStorage.php
+++ b/core/lib/Drupal/Core/Config/CachedStorage.php
@@ -8,7 +8,7 @@
 namespace Drupal\Core\Config;
 
 use Drupal\Core\Cache\Cache;
-use Drupal\Core\Cache\CacheBackendInterface;
+use Drupal\Core\Cache\CacheFactoryInterface;
 
 /**
  * Defines the cached storage.
@@ -27,6 +27,13 @@ class CachedStorage implements StorageInterface, StorageCacheInterface {
   protected $storage;
 
   /**
+   * The cache factory.
+   *
+   * @var \Drupal\Core\Cache\CacheFactoryInterface
+   */
+  protected $cacheFactory;
+
+  /**
    * The instantiated Cache backend.
    *
    * @var \Drupal\Core\Cache\CacheBackendInterface
@@ -45,12 +52,15 @@ class CachedStorage implements StorageInterface, StorageCacheInterface {
    *
    * @param \Drupal\Core\Config\StorageInterface $storage
    *   A configuration storage to be cached.
-   * @param \Drupal\Core\Cache\CacheBackendInterface $cache
-   *   A cache backend instance to use for caching.
+   * @param \Drupal\Core\Cache\CacheFactoryInterface $cache_factory
+   *   A cache factory used for getting cache backends.
+   * @param string $collection
+   *   (optional) The collection to store configuration in.
    */
-  public function __construct(StorageInterface $storage, CacheBackendInterface $cache) {
+  public function __construct(StorageInterface $storage, CacheFactoryInterface $cache_factory, $collection = '') {
     $this->storage = $storage;
-    $this->cache = $cache;
+    $this->cacheFactory = $cache_factory;
+    $this->setCollection($collection);
   }
 
   /**
@@ -238,4 +248,26 @@ public function deleteAll($prefix = '') {
   public function resetListCache() {
     $this->findByPrefixCache = array();
   }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setCollection($collection) {
+    if (empty($collection)) {
+      $bin = 'config';
+    }
+    else {
+      $bin = 'config_' . str_replace('.', '_', $collection);
+    }
+    $this->cache = $this->cacheFactory->get($bin);
+    $this->storage->setCollection($collection);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getCollections() {
+    return $this->storage->getCollections();
+  }
+
 }
diff --git a/core/lib/Drupal/Core/Config/DatabaseStorage.php b/core/lib/Drupal/Core/Config/DatabaseStorage.php
index 11ab691..2aa29f2 100644
--- a/core/lib/Drupal/Core/Config/DatabaseStorage.php
+++ b/core/lib/Drupal/Core/Config/DatabaseStorage.php
@@ -38,6 +38,13 @@ class DatabaseStorage implements StorageInterface {
   protected $options = array();
 
   /**
+   * The storage collection.
+   *
+   * @var string
+   */
+  protected $collection = '';
+
+  /**
    * Constructs a new DatabaseStorage.
    *
    * @param \Drupal\Core\Database\Connection $connection
@@ -46,11 +53,14 @@ class DatabaseStorage implements StorageInterface {
    *   A database table name to store configuration data in.
    * @param array $options
    *   (optional) Any additional database connection options to use in queries.
+   * @param string $collection
+   *   (optional) The collection to store configuration in.
    */
-  public function __construct(Connection $connection, $table, array $options = array()) {
+  public function __construct(Connection $connection, $table, array $options = array(), $collection = '') {
     $this->connection = $connection;
     $this->table = $table;
     $this->options = $options;
+    $this->collection = $collection;
   }
 
   /**
@@ -75,7 +85,7 @@ public function exists($name) {
   public function read($name) {
     $data = FALSE;
     try {
-      $raw = $this->connection->query('SELECT data FROM {' . $this->connection->escapeTable($this->table) . '} WHERE name = :name', array(':name' => $name), $this->options)->fetchField();
+      $raw = $this->connection->query('SELECT data FROM {' . $this->connection->escapeTable($this->table) . '} WHERE collection = :collection AND name = :name', array(':collection' => $this->collection, ':name' => $name), $this->options)->fetchField();
       if ($raw !== FALSE) {
         $data = $this->decode($raw);
       }
@@ -93,7 +103,7 @@ public function read($name) {
   public function readMultiple(array $names) {
     $list = array();
     try {
-      $list = $this->connection->query('SELECT name, data FROM {' . $this->connection->escapeTable($this->table) . '} WHERE name IN (:names)', array(':names' => $names), $this->options)->fetchAllKeyed();
+      $list = $this->connection->query('SELECT name, data FROM {' . $this->connection->escapeTable($this->table) . '} WHERE collection = :collection AND name IN (:names)', array(':collection' => $this->collection, ':names' => $names), $this->options)->fetchAllKeyed();
       foreach ($list as &$data) {
         $data = $this->decode($data);
       }
@@ -136,7 +146,7 @@ public function write($name, array $data) {
   protected function doWrite($name, $data) {
     $options = array('return' => Database::RETURN_AFFECTED) + $this->options;
     return (bool) $this->connection->merge($this->table, $options)
-      ->key('name', $name)
+      ->keys(array('collection', 'name'), array($this->collection, $name))
       ->fields(array('data' => $data))
       ->execute();
   }
@@ -176,8 +186,15 @@ protected static function schemaDefinition() {
     $schema = array(
       'description' => 'The base table for configuration data.',
       'fields' => array(
+        'collection' => array(
+          'description' => 'Primary Key: Config object collection.',
+          'type' => 'varchar',
+          'length' => 255,
+          'not null' => TRUE,
+          'default' => '',
+        ),
         'name' => array(
-          'description' => 'Primary Key: Unique config object name.',
+          'description' => 'Primary Key: Config object name.',
           'type' => 'varchar',
           'length' => 255,
           'not null' => TRUE,
@@ -190,7 +207,7 @@ protected static function schemaDefinition() {
           'size' => 'big',
         ),
       ),
-      'primary key' => array('name'),
+      'primary key' => array('collection', 'name'),
     );
     return $schema;
   }
@@ -205,6 +222,7 @@ protected static function schemaDefinition() {
   public function delete($name) {
     $options = array('return' => Database::RETURN_AFFECTED) + $this->options;
     return (bool) $this->connection->delete($this->table, $options)
+      ->condition('collection', $this->collection)
       ->condition('name', $name)
       ->execute();
   }
@@ -220,6 +238,7 @@ public function rename($name, $new_name) {
     return (bool) $this->connection->update($this->table, $options)
       ->fields(array('name' => $new_name))
       ->condition('name', $name)
+      ->condition('collection', $this->collection)
       ->execute();
   }
 
@@ -246,7 +265,8 @@ public function decode($raw) {
    */
   public function listAll($prefix = '') {
     try {
-      return $this->connection->query('SELECT name FROM {' . $this->connection->escapeTable($this->table) . '} WHERE name LIKE :name', array(
+      return $this->connection->query('SELECT name FROM {' . $this->connection->escapeTable($this->table) . '} WHERE collection = :collection AND name LIKE :name', array(
+        ':collection' => $this->collection,
         ':name' => $this->connection->escapeLike($prefix) . '%',
       ), $this->options)->fetchCol();
     }
@@ -263,10 +283,27 @@ public function deleteAll($prefix = '') {
       $options = array('return' => Database::RETURN_AFFECTED) + $this->options;
       return (bool) $this->connection->delete($this->table, $options)
         ->condition('name', $prefix . '%', 'LIKE')
+        ->condition('collection', $this->collection)
         ->execute();
     }
     catch (\Exception $e) {
       return FALSE;
     }
   }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setCollection($collection) {
+    $this->collection = $collection;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getCollections() {
+    return $this->connection->query('SELECT DISTINCT collection FROM {' . $this->connection->escapeTable($this->table) . '} WHERE collection <> \'\' ORDER by collection')->fetchCol();
+  }
+
+
 }
diff --git a/core/lib/Drupal/Core/Config/FileStorage.php b/core/lib/Drupal/Core/Config/FileStorage.php
index 1dac0f4..4f08e49 100644
--- a/core/lib/Drupal/Core/Config/FileStorage.php
+++ b/core/lib/Drupal/Core/Config/FileStorage.php
@@ -17,6 +17,13 @@
 class FileStorage implements StorageInterface {
 
   /**
+   * The storage collection.
+   *
+   * @var string
+   */
+  protected $collection;
+
+  /**
    * The filesystem path for configuration objects.
    *
    * @var string
@@ -28,9 +35,12 @@ class FileStorage implements StorageInterface {
    *
    * @param string $directory
    *   A directory path to use for reading and writing of configuration files.
+   * @param string $collection
+   *   (optional) The collection to store configuration in.
    */
-  public function __construct($directory) {
+  public function __construct($directory, $collection = '') {
     $this->directory = $directory;
+    $this->collection = $this->setCollection($collection);
   }
 
   /**
@@ -40,7 +50,7 @@ public function __construct($directory) {
    *   The path to the configuration file.
    */
   public function getFilePath($name) {
-    return $this->directory . '/' . $name . '.' . static::getFileExtension();
+    return $this->getCollectionDirectory() . '/' . $name . '.' . static::getFileExtension();
   }
 
   /**
@@ -57,10 +67,14 @@ public static function getFileExtension() {
    * Check if the directory exists and create it if not.
    */
   protected function ensureStorage() {
-    $success = file_prepare_directory($this->directory, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS);
-    $success = $success && file_save_htaccess($this->directory, TRUE, TRUE);
+    $dir = $this->getCollectionDirectory();
+    $success = file_prepare_directory($dir, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS);
+    // Only create .htaccess file in root driectory.
+    if ($dir == $this->directory) {
+      $success = $success && file_save_htaccess($this->directory, TRUE, TRUE);
+    }
     if (!$success) {
-      throw new StorageException("Failed to create config directory {$this->directory}");
+      throw new StorageException("Failed to create config directory {$dir}");
     }
     return $this;
   }
@@ -142,12 +156,22 @@ public function write($name, array $data) {
    */
   public function delete($name) {
     if (!$this->exists($name)) {
-      if (!file_exists($this->directory)) {
-        throw new StorageException($this->directory . '/ not found.');
+      $dir = $this->getCollectionDirectory();
+      if (!file_exists($dir)) {
+        throw new StorageException($dir . '/ not found.');
       }
       return FALSE;
     }
-    return drupal_unlink($this->getFilePath($name));
+    $success = drupal_unlink($this->getFilePath($name));
+
+    // If a collection is now empty remove the directory.
+    if ($success && !empty($this->collection)) {
+      $names = $this->listAll();
+      if (empty($names)) {
+        drupal_rmdir($this->getCollectionDirectory());
+      }
+    }
+    return $success;
   }
 
   /**
@@ -186,12 +210,13 @@ public function decode($raw) {
   public function listAll($prefix = '') {
     // glob() silently ignores the error of a non-existing search directory,
     // even with the GLOB_ERR flag.
-    if (!file_exists($this->directory)) {
+    $dir = $this->getCollectionDirectory();
+    if (!file_exists($dir)) {
       return array();
     }
     $extension = '.' . static::getFileExtension();
     // \GlobIterator on Windows requires an absolute path.
-    $files = new \GlobIterator(realpath($this->directory) . '/' . $prefix . '*' . $extension);
+    $files = new \GlobIterator(realpath($dir) . '/' . $prefix . '*' . $extension);
 
     $names = array();
     foreach ($files as $file) {
@@ -215,4 +240,60 @@ public function deleteAll($prefix = '') {
 
     return $success;
   }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setCollection($collection) {
+    $this->collection = $collection;
+  }
+
+  /**
+   * {@inheritdoc}
+   *
+   * @param string $directory
+   *   (optional) The directory to check for sub directories. This allows this
+   *   function to be used recursively to discover all the collections in the
+   *   storage. Defaults to an empty string which starts checking from the
+   *   storage's root directory.
+   */
+  public function getCollections($directory = '') {
+    $collections = array();
+    if (empty($directory)) {
+      $directory = $this->directory;
+    }
+    foreach (new \DirectoryIterator($directory) as $fileinfo) {
+      if ($fileinfo->isDir() && !$fileinfo->isDot()) {
+        $collection = $fileinfo->getFilename();
+        $sub_collections = $this->getCollections($directory . '/' . $collection);
+        if (empty($sub_collections)) {
+          $collections[] = $collection;
+        }
+        else {
+          foreach ($sub_collections as $sub_collection) {
+            $collections[] = $collection . '.' . $sub_collection;
+          }
+        }
+      }
+    }
+    sort($collections);
+    return $collections;
+  }
+
+  /**
+   * Gets the directory for the collection.
+   *
+   * @return string
+   *   The directory for the collection.
+   */
+  protected function getCollectionDirectory() {
+    if (empty($this->collection)) {
+      $dir = $this->directory;
+    }
+    else {
+      $dir = $this->directory . '/' . str_replace('.', '/', $this->collection);
+    }
+    return $dir;
+  }
+
 }
diff --git a/core/lib/Drupal/Core/Config/NullStorage.php b/core/lib/Drupal/Core/Config/NullStorage.php
index c66f718..7914bd9 100644
--- a/core/lib/Drupal/Core/Config/NullStorage.php
+++ b/core/lib/Drupal/Core/Config/NullStorage.php
@@ -92,4 +92,19 @@ public function listAll($prefix = '') {
   public function deleteAll($prefix = '') {
     return FALSE;
   }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setCollection($collection) {
+    // No op.
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getCollections() {
+    return array();
+  }
+
 }
diff --git a/core/lib/Drupal/Core/Config/StorageInterface.php b/core/lib/Drupal/Core/Config/StorageInterface.php
index 8b99784..d6251b4 100644
--- a/core/lib/Drupal/Core/Config/StorageInterface.php
+++ b/core/lib/Drupal/Core/Config/StorageInterface.php
@@ -156,4 +156,29 @@ public function listAll($prefix = '');
    */
   public function deleteAll($prefix = '');
 
+  /**
+   * Sets the collection on the storage.
+   *
+   * @param string $collection
+   *   The collection key. If not set then this is normal configuration
+   *   storage. However if set the storage needs to use it to differentiate the
+   *   collections. collections can be nested for example 'language.de'. If this
+   *   is a file system then we could create a language folder with a subfolder
+   *   named de. If this is a database table then there could be a collection
+   *   column which will store the value 'language.de'.
+   */
+  public function setCollection($collection);
+
+  /**
+   * Gets the existing collections.
+   *
+   * A configuration storage can contain multiple sets of configuration objects
+   * in partitioned collections. The collection key name identifies the current
+   * collection used.
+   *
+   * @return array
+   *   An array of existing collections.
+   */
+  public function getCollections();
+
 }
diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigImportRecreateTest.php b/core/modules/config/lib/Drupal/config/Tests/ConfigImportRecreateTest.php
index ac77a58..21ee6c5 100644
--- a/core/modules/config/lib/Drupal/config/Tests/ConfigImportRecreateTest.php
+++ b/core/modules/config/lib/Drupal/config/Tests/ConfigImportRecreateTest.php
@@ -42,7 +42,6 @@ public static function getInfo() {
   public function setUp() {
     parent::setUp();
 
-    $this->installSchema('system', 'config_snapshot');
     $this->installSchema('node', 'node');
 
     $this->copyConfig($this->container->get('config.storage'), $this->container->get('config.storage.staging'));
diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigImportRenameValidationTest.php b/core/modules/config/lib/Drupal/config/Tests/ConfigImportRenameValidationTest.php
index a538c12..f2ca9aa 100644
--- a/core/modules/config/lib/Drupal/config/Tests/ConfigImportRenameValidationTest.php
+++ b/core/modules/config/lib/Drupal/config/Tests/ConfigImportRenameValidationTest.php
@@ -51,7 +51,6 @@ public static function getInfo() {
   public function setUp() {
     parent::setUp();
 
-    $this->installSchema('system', 'config_snapshot');
     $this->installSchema('node', 'node');
 
     // Set up the ConfigImporter object for testing.
diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigImporterTest.php b/core/modules/config/lib/Drupal/config/Tests/ConfigImporterTest.php
index 341d3d4..b3c1633 100644
--- a/core/modules/config/lib/Drupal/config/Tests/ConfigImporterTest.php
+++ b/core/modules/config/lib/Drupal/config/Tests/ConfigImporterTest.php
@@ -43,8 +43,6 @@ public static function getInfo() {
   function setUp() {
     parent::setUp();
 
-    $this->installSchema('system', 'config_snapshot');
-
     $this->installConfig(array('config_test'));
     // Installing config_test's default configuration pollutes the global
     // variable being used for recording hook invocations by this test already,
diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigOverrideTest.php b/core/modules/config/lib/Drupal/config/Tests/ConfigOverrideTest.php
index 7c6c1cb..7359a35 100644
--- a/core/modules/config/lib/Drupal/config/Tests/ConfigOverrideTest.php
+++ b/core/modules/config/lib/Drupal/config/Tests/ConfigOverrideTest.php
@@ -31,7 +31,6 @@ public static function getInfo() {
 
   public function setUp() {
     parent::setUp();
-    $this->installSchema('system', 'config_snapshot');
     $this->copyConfig($this->container->get('config.storage'), $this->container->get('config.storage.staging'));
   }
 
diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigSnapshotTest.php b/core/modules/config/lib/Drupal/config/Tests/ConfigSnapshotTest.php
index 295ff74..a0b3ecc 100644
--- a/core/modules/config/lib/Drupal/config/Tests/ConfigSnapshotTest.php
+++ b/core/modules/config/lib/Drupal/config/Tests/ConfigSnapshotTest.php
@@ -32,7 +32,6 @@ public static function getInfo() {
 
   public function setUp() {
     parent::setUp();
-    $this->installSchema('system', 'config_snapshot');
     // Update the config snapshot. This allows the parent::setUp() to write
     // configuration files.
     \Drupal::service('config.manager')->createSnapshot(\Drupal::service('config.storage'), \Drupal::service('config.storage.snapshot'));
diff --git a/core/modules/config/lib/Drupal/config/Tests/DefaultConfigTest.php b/core/modules/config/lib/Drupal/config/Tests/DefaultConfigTest.php
index 9ce5cea..3a5b5d4 100644
--- a/core/modules/config/lib/Drupal/config/Tests/DefaultConfigTest.php
+++ b/core/modules/config/lib/Drupal/config/Tests/DefaultConfigTest.php
@@ -43,7 +43,7 @@ public function testDefaultConfig() {
     $typed_config = new TypedConfigManager(
       \Drupal::service('config.storage'),
       new TestInstallStorage(InstallStorage::CONFIG_SCHEMA_DIRECTORY),
-      \Drupal::service('cache.config')
+      \Drupal::service('cache.default')
     );
 
     // Create a configuration storage with access to default configuration in
diff --git a/core/modules/config/lib/Drupal/config/Tests/Storage/CachedStorageTest.php b/core/modules/config/lib/Drupal/config/Tests/Storage/CachedStorageTest.php
new file mode 100644
index 0000000..47f6891
--- /dev/null
+++ b/core/modules/config/lib/Drupal/config/Tests/Storage/CachedStorageTest.php
@@ -0,0 +1,120 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\config\Tests\Storage\CachedStorageTest.
+ */
+
+namespace Drupal\config\Tests\Storage;
+
+use Drupal\Core\Config\FileStorage;
+use Drupal\Core\Config\CachedStorage;
+use Drupal\Core\Database\Database;
+use Drupal\Core\DependencyInjection\ContainerBuilder;
+
+/**
+ * Tests CachedStorage operations.
+ */
+class CachedStorageTest extends ConfigStorageTestBase {
+
+  /**
+   * The cache backend the cached storage is using.
+   *
+   * @var \Drupal\Core\Cache\CacheBackendInterface
+   */
+  protected $cache;
+
+  /**
+   * The file storage the cached storage is using.
+   *
+   * @var \Drupal\Core\Config\FileStorage
+   */
+  protected $filestorage;
+
+  public static function getInfo() {
+    return array(
+      'name' => 'CachedStorage operations',
+      'description' => 'Tests CachedStorage operations.',
+      'group' => 'Configuration',
+    );
+  }
+
+  function setUp() {
+    parent::setUp();
+    $this->filestorage = new FileStorage($this->configDirectories[CONFIG_ACTIVE_DIRECTORY]);
+    $this->storage = new CachedStorage($this->filestorage, \Drupal::service('cache_factory'));
+    $this->cache = \Drupal::service('cache_factory')->get('config');
+    // ::listAll() verifications require other configuration data to exist.
+    $this->storage->write('system.performance', array());
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function testInvalidStorage() {
+    // No-op as this test does not make sense.
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function testInvalidData() {
+    // No-op as this test does not make sense.
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function read($name) {
+    $data = $this->cache->get($name);
+    // Cache misses fall through to the underlying storage.
+    return $data ? $data->data : $this->filestorage->read($name);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function insert($name, $data) {
+    // Try writing to the file storage first catch exceptions so that we can do
+    // the invalid data tests.
+    try {
+      $this->filestorage->write($name, $data);
+      $this->cache->set($name, $data);
+    }
+    catch (\Exception $e) {
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function update($name, $data) {
+    // Try writing to the file storage first catch exceptions so that we can do
+    // the invalid data tests.
+    try {
+      $this->filestorage->write($name, $data);
+      $this->cache->set($name, $data);
+    }
+    catch (\Exception $e) {
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function delete($name) {
+    $this->cache->delete($name);
+    unlink($this->filestorage->getFilePath($name));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function containerBuild(ContainerBuilder $container) {
+    parent::containerBuild($container);
+    // Use the regular database cache backend to aid testing.
+    $container->register('cache_factory', 'Drupal\Core\Cache\DatabaseBackendFactory')
+      ->addArgument(Database::getConnection());
+  }
+
+}
diff --git a/core/modules/config/lib/Drupal/config/Tests/Storage/ConfigStorageTestBase.php b/core/modules/config/lib/Drupal/config/Tests/Storage/ConfigStorageTestBase.php
index 925ecbd..6ad56d8 100644
--- a/core/modules/config/lib/Drupal/config/Tests/Storage/ConfigStorageTestBase.php
+++ b/core/modules/config/lib/Drupal/config/Tests/Storage/ConfigStorageTestBase.php
@@ -24,6 +24,11 @@
 abstract class ConfigStorageTestBase extends DrupalUnitTestBase {
 
   /**
+   * @var \Drupal\Core\Config\StorageInterface;
+   */
+  protected $storage;
+
+  /**
    * Tests storage CRUD operations.
    *
    * @todo Coverage: Trigger PDOExceptions / Database exceptions.
@@ -38,17 +43,6 @@ function testCRUD() {
     $data = $this->storage->read($name);
     $this->assertIdentical($data, FALSE);
 
-    // Reading a name containing non-decodeable data returns FALSE.
-    $this->insert($name, '');
-    $data = $this->storage->read($name);
-    $this->assertIdentical($data, FALSE);
-
-    $this->update($name, 'foo');
-    $data = $this->storage->read($name);
-    $this->assertIdentical($data, FALSE);
-
-    $this->delete($name);
-
     // Writing data returns TRUE and the data has been written.
     $data = array('foo' => 'bar');
     $result = $this->storage->write($name, $data);
@@ -90,14 +84,6 @@ function testCRUD() {
     $result = $this->storage->delete($name);
     $this->assertIdentical($result, FALSE);
 
-    // Reading from a non-existing storage bin returns FALSE.
-    $result = $this->invalidStorage->read($name);
-    $this->assertIdentical($result, FALSE);
-
-    // Listing on a non-existing storage bin returns an empty array.
-    $result = $this->invalidStorage->listAll();
-    $this->assertIdentical($result, array());
-
     // Deleting all names with prefix deletes the appropriate data and returns
     // TRUE.
     $files = array(
@@ -114,35 +100,57 @@ function testCRUD() {
     $this->assertIdentical($result, TRUE);
     $this->assertIdentical($names, array());
 
-
-    // Deleting from a non-existing storage bin throws an exception.
+    // Test renaming an object that does not exist throws an exception.
     try {
-      $this->invalidStorage->delete($name);
-      $this->fail('Exception not thrown upon deleting from a non-existing storage bin.');
+      $this->storage->rename('config_test.storage_does_not_exist', 'config_test.storage_does_not_exist_rename');
     }
     catch (\Exception $e) {
       $class = get_class($e);
-      $this->pass($class . ' thrown upon deleting from a non-existing storage bin.');
+      $this->pass($class . ' thrown upon renaming a nonexistent storage bin.');
     }
 
-    // Test renaming an object that does not exist throws an exception.
+    // Test renaming to an object that already exists throws an exception.
     try {
-      $this->storage->rename('config_test.storage_does_not_exist', 'config_test.storage_does_not_exist_rename');
+      $this->storage->rename('system.cron', 'system.performance');
     }
     catch (\Exception $e) {
       $class = get_class($e);
       $this->pass($class . ' thrown upon renaming a nonexistent storage bin.');
     }
+  }
 
-    // Test renaming to an object that already exists throws an exception.
+  /**
+   * Tests an invalid storage.
+   */
+  public function testInvalidStorage() {
+    $name = 'config_test.storage';
+
+    // Write something to the valid storage to prove that the storages do not
+    // pollute one another.
+    $data = array('foo' => 'bar');
+    $result = $this->storage->write($name, $data);
+    $this->assertIdentical($result, TRUE);
+
+    $raw_data = $this->read($name);
+    $this->assertIdentical($raw_data, $data);
+
+    // Reading from a non-existing storage bin returns FALSE.
+    $result = $this->invalidStorage->read($name);
+    $this->assertIdentical($result, FALSE);
+
+    // Deleting from a non-existing storage bin throws an exception.
     try {
-      $this->storage->rename('system.cron', 'system.performance');
+      $this->invalidStorage->delete($name);
+      $this->fail('Exception not thrown upon deleting from a non-existing storage bin.');
     }
     catch (\Exception $e) {
       $class = get_class($e);
-      $this->pass($class . ' thrown upon renaming a nonexistent storage bin.');
+      $this->pass($class . ' thrown upon deleting from a non-existing storage bin.');
     }
 
+    // Listing on a non-existing storage bin returns an empty array.
+    $result = $this->invalidStorage->listAll();
+    $this->assertIdentical($result, array());
     // Writing to a non-existing storage bin creates the bin.
     $this->invalidStorage->write($name, array('foo' => 'bar'));
     $result = $this->invalidStorage->read($name);
@@ -150,6 +158,22 @@ function testCRUD() {
   }
 
   /**
+   * Test that invalid data can not be read from the storage.
+   */
+  public function testInvalidData() {
+    $name = 'config_test.storage';
+
+    // Reading a name containing non-decodeable data returns FALSE.
+    $this->insert($name, '');
+    $data = $this->storage->read($name);
+    $this->assertIdentical($data, FALSE);
+
+    $this->update($name, 'foo');
+    $data = $this->storage->read($name);
+    $this->assertIdentical($data, FALSE);
+  }
+
+  /**
    * Tests storage writing and reading data preserving data type.
    */
   function testDataTypes() {
@@ -180,4 +204,57 @@ function testDataTypes() {
   abstract protected function update($name, $data);
 
   abstract protected function delete($name);
+
+  public function testCollection() {
+    $name = 'config_test.storage';
+    $data = array('foo => bar');
+    $result = $this->storage->write($name, $data);
+    $this->assertIdentical($result, TRUE);
+    $this->assertIdentical($data, $this->storage->read($name));
+
+    // Create configuration in a new collection.
+    $this->storage->setCollection('collection.new');
+    $this->storage->write($name, $data);
+    $this->assertIdentical($result, TRUE);
+    $this->assertIdentical($data, $this->storage->read($name));
+    $new_data = array('foo' => 'baz');
+    $this->storage->write($name, $new_data);
+    $this->assertIdentical($result, TRUE);
+    $this->assertIdentical($new_data, $this->storage->read($name));
+
+    // Create configuration in another collection.
+    $this->storage->setCollection('collection.another');
+    $this->storage->write($name, $new_data);
+    $this->assertIdentical($result, TRUE);
+    $this->assertIdentical($new_data, $this->storage->read($name));
+
+    // Create configuration in yet another collection.
+    $this->storage->setCollection('alternate');
+    $this->storage->write($name, $new_data);
+    $this->assertIdentical($result, TRUE);
+    $this->assertIdentical($new_data, $this->storage->read($name));
+
+    // Switch back to the collection-less mode and check the data still exists
+    // add has not been touched.
+    $this->storage->setCollection('');
+    $this->assertIdentical($data, $this->storage->read($name));
+
+    // Check that the getCollections() method works.
+    $this->assertIdentical(array('alternate', 'collection.another', 'collection.new'), $this->storage->getCollections());
+
+    // Check that the collections are removed when they are empty.
+    $this->storage->setCollection('alternate');
+    $this->storage->delete($name);
+    $this->assertIdentical(array('collection.another', 'collection.new'), $this->storage->getCollections());
+
+    // Check that the having an empty collection-less storage does not break
+    // anything.
+    $this->storage->setCollection('');
+    // Before deleting check that the previous delete did not affect data in
+    // another collection.
+    $this->assertIdentical($data, $this->storage->read($name));
+    $this->storage->delete($name);
+    $this->assertIdentical(array('collection.another', 'collection.new'), $this->storage->getCollections());
+  }
+
 }
diff --git a/core/modules/field/lib/Drupal/field/Tests/FieldUnitTestBase.php b/core/modules/field/lib/Drupal/field/Tests/FieldUnitTestBase.php
index 5f77d92..5717a23 100644
--- a/core/modules/field/lib/Drupal/field/Tests/FieldUnitTestBase.php
+++ b/core/modules/field/lib/Drupal/field/Tests/FieldUnitTestBase.php
@@ -37,7 +37,7 @@
   function setUp() {
     parent::setUp();
     $this->installSchema('entity_test', 'entity_test');
-    $this->installSchema('system', array('sequences', 'config_snapshot'));
+    $this->installSchema('system', array('sequences'));
     $this->installSchema('user', array('users', 'users_roles'));
 
     // Set default storage backend and configure the theme system.
diff --git a/core/modules/locale/locale.services.yml b/core/modules/locale/locale.services.yml
index af97659..c6e9838 100644
--- a/core/modules/locale/locale.services.yml
+++ b/core/modules/locale/locale.services.yml
@@ -1,7 +1,7 @@
 services:
   locale.config.typed:
     class: Drupal\locale\LocaleConfigManager
-    arguments: ['@config.storage', '@config.storage.schema', '@config.storage.installer', '@locale.storage', '@cache.config', '@config.factory', '@language_manager']
+    arguments: ['@config.storage', '@config.storage.schema', '@config.storage.installer', '@locale.storage', '@cache.default', '@config.factory', '@language_manager']
   locale.storage:
     class: Drupal\locale\StringDatabaseStorage
     arguments: ['@database']
diff --git a/core/modules/node/lib/Drupal/node/Tests/Config/NodeImportChangeTest.php b/core/modules/node/lib/Drupal/node/Tests/Config/NodeImportChangeTest.php
index bdd2b92..f848870 100644
--- a/core/modules/node/lib/Drupal/node/Tests/Config/NodeImportChangeTest.php
+++ b/core/modules/node/lib/Drupal/node/Tests/Config/NodeImportChangeTest.php
@@ -26,9 +26,6 @@ class NodeImportChangeTest extends DrupalUnitTestBase {
    */
   public function setUp() {
     parent::setUp();
-
-    $this->installSchema('system', array('config_snapshot'));
-
     // Set default storage backend.
     $this->installConfig(array('field', 'node_test_config'));
   }
diff --git a/core/modules/node/lib/Drupal/node/Tests/Config/NodeImportCreateTest.php b/core/modules/node/lib/Drupal/node/Tests/Config/NodeImportCreateTest.php
index 1d59ca1..cbc2920 100644
--- a/core/modules/node/lib/Drupal/node/Tests/Config/NodeImportCreateTest.php
+++ b/core/modules/node/lib/Drupal/node/Tests/Config/NodeImportCreateTest.php
@@ -26,8 +26,6 @@ class NodeImportCreateTest extends DrupalUnitTestBase {
    */
   public function setUp() {
     parent::setUp();
-
-    $this->installSchema('system', array('config_snapshot'));
     $this->installSchema('user', array('users'));
 
     // Set default storage backend.
diff --git a/core/modules/system/system.install b/core/modules/system/system.install
index 820efa7..a14cd7b 100644
--- a/core/modules/system/system.install
+++ b/core/modules/system/system.install
@@ -956,25 +956,5 @@ function system_schema() {
     ),
   );
 
-  $schema['config_snapshot'] = array(
-    'description' => 'Stores a snapshot of the last imported configuration.',
-    'fields' => array(
-      'name' => array(
-        'description' => 'The identifier for the config object (the name of the file, minus the file extension).',
-        'type' => 'varchar',
-        'length' => 255,
-        'not null' => TRUE,
-        'default' => '',
-      ),
-      'data' => array(
-        'description' => 'The raw data for this configuration object.',
-        'type' => 'blob',
-        'not null' => TRUE,
-        'size' => 'big',
-      ),
-    ),
-    'primary key' => array('name'),
-  );
-
   return $schema;
 }
diff --git a/core/tests/Drupal/Tests/Core/Config/CachedStorageTest.php b/core/tests/Drupal/Tests/Core/Config/CachedStorageTest.php
index 6c60af4..e751e08 100644
--- a/core/tests/Drupal/Tests/Core/Config/CachedStorageTest.php
+++ b/core/tests/Drupal/Tests/Core/Config/CachedStorageTest.php
@@ -15,6 +15,11 @@
  */
 class CachedStorageTest extends UnitTestCase {
 
+  /**
+   * @var \Drupal\Core\Cache\CacheFactoryInterface|\PHPUnit_Framework_MockObject_MockObject
+   */
+  protected $cacheFactory;
+
   public static function getInfo() {
     return array(
       'name' => 'Config cached storage test',
@@ -23,6 +28,10 @@ public static function getInfo() {
     );
   }
 
+  public function setUp() {
+    $this->cacheFactory = $this->getMock('Drupal\Core\Cache\CacheFactoryInterface');
+  }
+
   /**
    * Test listAll static cache.
    */
@@ -37,7 +46,11 @@ public function testListAllStaticCache() {
       ->will($this->returnValue($response));
 
     $cache = new NullBackend(__FUNCTION__);
-    $cachedStorage = new CachedStorage($storage, $cache);
+    $this->cacheFactory->expects($this->once())
+      ->method('get')
+      ->with('config')
+      ->will($this->returnValue($cache));
+    $cachedStorage = new CachedStorage($storage, $this->cacheFactory);
     $this->assertEquals($response, $cachedStorage->listAll($prefix));
     $this->assertEquals($response, $cachedStorage->listAll($prefix));
   }
@@ -53,7 +66,11 @@ public function testListAllPrimedPersistentCache() {
     $response = array("$prefix." . $this->randomName(), "$prefix." . $this->randomName());
     $cache = new MemoryBackend(__FUNCTION__);
     $cache->set('find:' . $prefix, $response);
-    $cachedStorage = new CachedStorage($storage, $cache);
+    $this->cacheFactory->expects($this->once())
+      ->method('get')
+      ->with('config')
+      ->will($this->returnValue($cache));
+    $cachedStorage = new CachedStorage($storage, $this->cacheFactory);
     $this->assertEquals($response, $cachedStorage->listAll($prefix));
   }
 
@@ -79,7 +96,11 @@ public function testGetMultipleOnPrimedCache() {
     foreach ($configCacheValues as $key => $value) {
       $cache->set($key, $value);
     }
-    $cachedStorage = new CachedStorage($storage, $cache);
+    $this->cacheFactory->expects($this->once())
+      ->method('get')
+      ->with('config')
+      ->will($this->returnValue($cache));
+    $cachedStorage = new CachedStorage($storage, $this->cacheFactory);
     $this->assertEquals($configCacheValues, $cachedStorage->readMultiple($configNames));
   }
 
@@ -119,7 +140,11 @@ public function testGetMultipleOnPartiallyPrimedCache() {
       ->with(array(2 => $configNames[2], 4 => $configNames[4]))
       ->will($this->returnValue($response));
 
-    $cachedStorage = new CachedStorage($storage, $cache);
+    $this->cacheFactory->expects($this->once())
+      ->method('get')
+      ->with('config')
+      ->will($this->returnValue($cache));
+    $cachedStorage = new CachedStorage($storage, $this->cacheFactory);
     $expected_data = $configCacheValues + array($configNames[2] => $config_exists_not_cached_data);
     $this->assertEquals($expected_data, $cachedStorage->readMultiple($configNames));
 
@@ -143,7 +168,11 @@ public function testReadNonExistentFileCacheMiss() {
             ->method('read')
             ->with($name)
             ->will($this->returnValue(FALSE));
-    $cachedStorage = new CachedStorage($storage, $cache);
+    $this->cacheFactory->expects($this->once())
+      ->method('get')
+      ->with('config')
+      ->will($this->returnValue($cache));
+    $cachedStorage = new CachedStorage($storage, $this->cacheFactory);
 
     $this->assertFalse($cachedStorage->read($name));
 
@@ -163,7 +192,11 @@ public function testReadNonExistentFileCached() {
     $storage = $this->getMock('Drupal\Core\Config\StorageInterface');
     $storage->expects($this->never())
             ->method('read');
-    $cachedStorage = new CachedStorage($storage, $cache);
+    $this->cacheFactory->expects($this->once())
+      ->method('get')
+      ->with('config')
+      ->will($this->returnValue($cache));
+    $cachedStorage = new CachedStorage($storage, $this->cacheFactory);
     $this->assertFalse($cachedStorage->read($name));
   }
 
