diff --git a/core/core.services.yml b/core/core.services.yml
index b6decf3..e6395ee 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -28,13 +28,16 @@ services:
       - { name: cache.context}
   cache.backend.database:
     class: Drupal\Core\Cache\DatabaseBackendFactory
-    arguments: ['@database']
+    arguments: ['@database', '@cache_tag']
   cache.backend.apcu:
     class: Drupal\Core\Cache\ApcuBackendFactory
+    arguments: ['@cache_tag']
   cache.backend.php:
     class: Drupal\Core\Cache\PhpBackendFactory
+    arguments: ['@cache_tag']
   cache.backend.memory:
     class: Drupal\Core\Cache\MemoryBackendFactory
+    arguments: ['@cache_tag']
   cache.backend.null:
     class: Drupal\Core\Cache\NullBackendFactory
   cache.bootstrap:
@@ -79,6 +82,13 @@ services:
     factory_method: get
     factory_service: cache_factory
     arguments: [discovery]
+  cache_tag:
+    class: Drupal\Core\Cache\DatabaseTagBackend
+    arguments: ['@database']
+  config.cachedstorage.storage:
+    class: Drupal\Core\Config\FileStorage
+    factory_class: Drupal\Core\Config\FileStorageFactory
+    factory_method: getActive
   config.manager:
     class: Drupal\Core\Config\ConfigManager
     arguments: ['@entity.manager', '@config.factory', '@config.typed', '@string_translation', '@config.storage', '@event_dispatcher']
diff --git a/core/lib/Drupal/Core/Cache/BackendChain.php b/core/lib/Drupal/Core/Cache/BackendChain.php
index 0cea142..4ff5c75 100644
--- a/core/lib/Drupal/Core/Cache/BackendChain.php
+++ b/core/lib/Drupal/Core/Cache/BackendChain.php
@@ -159,15 +159,6 @@ public function deleteMultiple(array $cids) {
   }
 
   /**
-   * Implements Drupal\Core\Cache\CacheBackendInterface::deleteTags().
-   */
-  public function deleteTags(array $tags) {
-    foreach ($this->backends as $backend) {
-      $backend->deleteTags($tags);
-    }
-  }
-
-  /**
    * Implements Drupal\Core\Cache\CacheBackendInterface::deleteAll().
    */
   public function deleteAll() {
@@ -195,15 +186,6 @@ public function invalidateMultiple(array $cids) {
   }
 
   /**
-   * Implements Drupal\Core\Cache\CacheBackendInterface::invalidateTags().
-   */
-  public function invalidateTags(array $tags) {
-    foreach ($this->backends as $backend) {
-      $backend->invalidateTags($tags);
-    }
-  }
-
-  /**
    * Implements Drupal\Core\Cache\CacheBackendInterface::invalidateAll().
    */
   public function invalidateAll() {
diff --git a/core/lib/Drupal/Core/Cache/Cache.php b/core/lib/Drupal/Core/Cache/Cache.php
index ad59409..3c7f50b 100644
--- a/core/lib/Drupal/Core/Cache/Cache.php
+++ b/core/lib/Drupal/Core/Cache/Cache.php
@@ -24,46 +24,28 @@ class Cache {
   /**
    * Deletes items from all bins with any of the specified tags.
    *
-   * Many sites have more than one active cache backend, and each backend may
-   * use a different strategy for storing tags against cache items, and
-   * deleting cache items associated with a given tag.
-   *
-   * When deleting a given list of tags, we iterate over each cache backend, and
-   * and call deleteTags() on each.
-   *
    * @param array $tags
    *   The list of tags to delete cache items for.
    */
   public static function deleteTags(array $tags) {
-    foreach (static::getBins() as $cache_backend) {
-      $cache_backend->deleteTags($tags);
-    }
+    \Drupal::service('cache_tag')->deleteTags($tags);
   }
 
   /**
    * Marks cache items from all bins with any of the specified tags as invalid.
    *
-   * Many sites have more than one active cache backend, and each backend my use
-   * a different strategy for storing tags against cache items, and invalidating
-   * cache items associated with a given tag.
-   *
-   * When invalidating a given list of tags, we iterate over each cache backend,
-   * and call invalidateTags() on each.
-   *
    * @param array $tags
    *   The list of tags to invalidate cache items for.
    */
   public static function invalidateTags(array $tags) {
-    foreach (static::getBins() as $cache_backend) {
-      $cache_backend->invalidateTags($tags);
-    }
+    \Drupal::service('cache_tag')->invalidateTags($tags);
   }
 
   /**
    * Gets all cache bin services.
    *
    * @return array
-   *  An array of cache backend objects keyed by cache bins.
+   *  An array of cache bin objects keyed by cache bin.
    */
   public static function getBins() {
     $bins = array();
diff --git a/core/lib/Drupal/Core/Cache/CacheBackendInterface.php b/core/lib/Drupal/Core/Cache/CacheBackendInterface.php
index 753e6a3..ad41e0d 100644
--- a/core/lib/Drupal/Core/Cache/CacheBackendInterface.php
+++ b/core/lib/Drupal/Core/Cache/CacheBackendInterface.php
@@ -134,7 +134,7 @@ public function setMultiple(array $items);
    *
    * @see \Drupal\Core\Cache\CacheBackendInterface::invalidate()
    * @see \Drupal\Core\Cache\CacheBackendInterface::deleteMultiple()
-   * @see \Drupal\Core\Cache\CacheBackendInterface::deleteTags()
+   * @see \Drupal\Core\Cache\CacheTagBackendInterface::deleteTags()
    * @see \Drupal\Core\Cache\CacheBackendInterface::deleteAll()
    */
   public function delete($cid);
@@ -153,39 +153,18 @@ public function delete($cid);
    *
    * @see \Drupal\Core\Cache\CacheBackendInterface::invalidateMultiple()
    * @see \Drupal\Core\Cache\CacheBackendInterface::delete()
-   * @see \Drupal\Core\Cache\CacheBackendInterface::deleteTags()
+   * @see \Drupal\Core\Cache\CacheTagBackendInterface::deleteTags()
    * @see \Drupal\Core\Cache\CacheBackendInterface::deleteAll()
    */
   public function deleteMultiple(array $cids);
 
   /**
-   * Deletes items with any of the specified tags.
-   *
-   * If the cache items are being deleted because they are no longer "fresh",
-   * you may consider using invalidateTags() instead. This allows callers to
-   * retrieve the invalid items by calling get() with $allow_invalid set to TRUE.
-   * In some cases an invalid item may be acceptable rather than having to
-   * rebuild the cache.
-   *
-   * @param array $tags
-   *   Associative array of tags, in the same format that is passed to
-   *   CacheBackendInterface::set().
-   *
-   * @see \Drupal\Core\Cache\CacheBackendInterface::set()
-   * @see \Drupal\Core\Cache\CacheBackendInterface::invalidateTags()
-   * @see \Drupal\Core\Cache\CacheBackendInterface::delete()
-   * @see \Drupal\Core\Cache\CacheBackendInterface::deleteMultiple()
-   * @see \Drupal\Core\Cache\CacheBackendInterface::deleteAll()
-   */
-  public function deleteTags(array $tags);
-
-  /**
    * Deletes all cache items in a bin.
    *
    * @see \Drupal\Core\Cache\CacheBackendInterface::invalidateAll()
    * @see \Drupal\Core\Cache\CacheBackendInterface::delete()
    * @see \Drupal\Core\Cache\CacheBackendInterface::deleteMultiple()
-   * @see \Drupal\Core\Cache\CacheBackendInterface::deleteTags()
+   * @see \Drupal\Core\Cache\CacheTagBackendInterface::deleteTags()
    */
   public function deleteAll();
 
@@ -200,7 +179,7 @@ public function deleteAll();
    *
    * @see \Drupal\Core\Cache\CacheBackendInterface::delete()
    * @see \Drupal\Core\Cache\CacheBackendInterface::invalidateMultiple()
-   * @see \Drupal\Core\Cache\CacheBackendInterface::invalidateTags()
+   * @see \Drupal\Core\Cache\CacheTagBackendInterface::invalidateTags()
    * @see \Drupal\Core\Cache\CacheBackendInterface::invalidateAll()
    */
   public function invalidate($cid);
@@ -216,27 +195,12 @@ public function invalidate($cid);
    *
    * @see \Drupal\Core\Cache\CacheBackendInterface::deleteMultiple()
    * @see \Drupal\Core\Cache\CacheBackendInterface::invalidate()
-   * @see \Drupal\Core\Cache\CacheBackendInterface::invalidateTags()
+   * @see \Drupal\Core\Cache\CacheTagBackendInterface::invalidateTags()
    * @see \Drupal\Core\Cache\CacheBackendInterface::invalidateAll()
    */
   public function invalidateMultiple(array $cids);
 
   /**
-   * Marks cache items with any of the specified tags as invalid.
-   *
-   * @param array $tags
-   *   Associative array of tags, in the same format that is passed to
-   *   CacheBackendInterface::set().
-   *
-   * @see \Drupal\Core\Cache\CacheBackendInterface::set()
-   * @see \Drupal\Core\Cache\CacheBackendInterface::deleteTags()
-   * @see \Drupal\Core\Cache\CacheBackendInterface::invalidate()
-   * @see \Drupal\Core\Cache\CacheBackendInterface::invalidateMultiple()
-   * @see \Drupal\Core\Cache\CacheBackendInterface::invalidateAll()
-   */
-  public function invalidateTags(array $tags);
-
-  /**
    * Marks all cache items as invalid.
    *
    * Invalid items may be returned in later calls to get(), if the $allow_invalid
@@ -248,7 +212,7 @@ public function invalidateTags(array $tags);
    * @see \Drupal\Core\Cache\CacheBackendInterface::deleteAll()
    * @see \Drupal\Core\Cache\CacheBackendInterface::invalidate()
    * @see \Drupal\Core\Cache\CacheBackendInterface::invalidateMultiple()
-   * @see \Drupal\Core\Cache\CacheBackendInterface::invalidateTags()
+   * @see \Drupal\Core\Cache\CacheTagBackendInterface::invalidateTags()
    */
   public function invalidateAll();
 
diff --git a/core/lib/Drupal/Core/Cache/CacheTagBackendBase.php b/core/lib/Drupal/Core/Cache/CacheTagBackendBase.php
new file mode 100644
index 0000000..4e2c190
--- /dev/null
+++ b/core/lib/Drupal/Core/Cache/CacheTagBackendBase.php
@@ -0,0 +1,36 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Cache\CacheTagBase.
+ */
+
+namespace Drupal\Core\Cache;
+
+/**
+ * Class CacheTagBase
+ */
+abstract class CacheTagBackendBase implements CacheTagBackendInterface {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function flattenTags(array $tags) {
+    if (isset($tags[0])) {
+      return $tags;
+    }
+
+    $flat_tags = array();
+    foreach ($tags as $namespace => $values) {
+      if (is_array($values)) {
+        foreach ($values as $value) {
+          $flat_tags[] = "$namespace:$value";
+        }
+      }
+      else {
+        $flat_tags[] = "$namespace:$values";
+      }
+    }
+    return $flat_tags;
+  }
+}
diff --git a/core/lib/Drupal/Core/Cache/CacheTagBackendFactory.php b/core/lib/Drupal/Core/Cache/CacheTagBackendFactory.php
new file mode 100644
index 0000000..099b503
--- /dev/null
+++ b/core/lib/Drupal/Core/Cache/CacheTagBackendFactory.php
@@ -0,0 +1,57 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Cache\CacheTagFactory.
+ */
+
+namespace Drupal\Core\Cache;
+
+use Drupal\Core\Site\Settings;
+use Symfony\Component\DependencyInjection\ContainerAware;
+
+/**
+ * Defines a cache tag backend factory.
+ */
+class CacheTagBackendFactory extends ContainerAware {
+
+  /**
+   * The settings array.
+   *
+   * @var \Drupal\Component\Utility\Settings
+   */
+  protected $settings;
+
+  /**
+   * Constructs CacheTagBackendFactory object.
+   *
+   * @param \Drupal\Component\Utility\Settings $settings
+   *   The settings array.
+   */
+  function __construct(Settings $settings) {
+    $this->settings = $settings;
+  }
+
+  /**
+   * Instantiates a cache tag class.
+   *
+   * By default, this returns an instance of the
+   * Drupal\Core\Cache\DatabaseBackendTag class.
+   *
+   * @return \Drupal\Core\Cache\CacheTagBackendInterface
+   *   The cache tag instance.
+   */
+  public function get() {
+    $cache_tag_service = $this->settings->get('cache_tag_service');
+
+    if (isset($cache_tag_service)) {
+      $service_name = $cache_tag_service;
+    }
+    else {
+      $service_name = 'cache.tag.database';
+    }
+
+    return $this->container->get($service_name);
+  }
+
+}
diff --git a/core/lib/Drupal/Core/Cache/CacheTagBackendInterface.php b/core/lib/Drupal/Core/Cache/CacheTagBackendInterface.php
new file mode 100644
index 0000000..ca31af1
--- /dev/null
+++ b/core/lib/Drupal/Core/Cache/CacheTagBackendInterface.php
@@ -0,0 +1,74 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Cache\CacheTagBackendInterface.
+ */
+
+namespace Drupal\Core\Cache;
+
+/**
+ * Class CacheTagBackendInterface.
+ */
+interface CacheTagBackendInterface {
+
+  /**
+   * Marks specified cache tags as deleted.
+   *
+   * If the cache items are being deleted because they are no longer "fresh",
+   * you may consider using invalidateTags() instead. This allows callers to
+   * retrieve the invalid items by calling get() with $allow_invalid set to TRUE.
+   * In some cases an invalid item may be acceptable rather than having to
+   * rebuild the cache.
+   *
+   * @param array $tags
+   *   Associative array of tags.
+   */
+  public function deleteTags(array $tags);
+
+  /**
+   * Marks specified cache tags as invalid.
+   *
+   * @param array $tags
+   *   Associative array of tags.
+   */
+  public function invalidateTags(array $tags);
+
+  /**
+   * 'Flattens' a tags array into an array of strings.
+   *
+   * @param array $tags
+   *   Associative array of tags to flatten.
+   *
+   * @return array
+   *   An indexed array of flattened tag identifiers.
+   */
+  public function flattenTags(array $tags);
+
+  /**
+   * Returns the sum total of validations for a given set of tags.
+   *
+   * @param array $tags
+   *   Associative array of tags.
+   * @param bool $set_context
+   *   TRUE if called from set context.
+   *
+   * @return array
+   *   Array with two items (invalidations, deletions) providing sum of all
+   *   invalidations/deletions over all provided tags.
+   */
+  public function checksumTags(array $tags, $set_context);
+
+  /**
+   * Prepares cache item before it is returned from cache backend interface.
+   *
+   * $item->deleted should be set to TRUE if item was deleted via tags and
+   * $item->valid should be set to FALSE if item was invalidated.
+   */
+  public function prepareGet(&$item);
+
+  /**
+   * Clears cache tag service internal caches.
+   */
+  public function clearCache();
+}
diff --git a/core/lib/Drupal/Core/Cache/DatabaseBackend.php b/core/lib/Drupal/Core/Cache/DatabaseBackend.php
index 09e7e82..034b5b6 100644
--- a/core/lib/Drupal/Core/Cache/DatabaseBackend.php
+++ b/core/lib/Drupal/Core/Cache/DatabaseBackend.php
@@ -25,7 +25,6 @@ class DatabaseBackend implements CacheBackendInterface {
    */
   protected $bin;
 
-
   /**
    * The database connection.
    *
@@ -34,19 +33,30 @@ class DatabaseBackend implements CacheBackendInterface {
   protected $connection;
 
   /**
+   * The cache tag service.
+   *
+   * @var \Drupal\Core\Cache\CacheTagBackendInterface
+   */
+  protected $cacheTag;
+
+  /**
    * Constructs a DatabaseBackend object.
    *
    * @param \Drupal\Core\Database\Connection $connection
    *   The database connection.
+   * @param \Drupal\Core\Cache\CacheTagBackendInterface
+   *   The cache tag service.
    * @param string $bin
    *   The cache bin for which the object is created.
    */
-  public function __construct(Connection $connection, $bin) {
+  public function __construct(Connection $connection, CacheTagBackendInterface $cache_tag, $bin) {
     // All cache tables should be prefixed with 'cache_'.
     $bin = 'cache_' . $bin;
 
     $this->bin = $bin;
+
     $this->connection = $connection;
+    $this->cacheTag = $cache_tag;
   }
 
   /**
@@ -109,19 +119,17 @@ protected function prepareItem($cache, $allow_invalid) {
 
     $cache->tags = $cache->tags ? explode(' ', $cache->tags) : array();
 
-    $checksum = $this->checksumTags($cache->tags);
-
-    // Check if deleteTags() has been called with any of the entry's tags.
-    if ($cache->checksum_deletions != $checksum['deletions']) {
-      return FALSE;
-    }
-
     // Check expire time.
-    $cache->valid = $cache->expire == Cache::PERMANENT || $cache->expire >= REQUEST_TIME;
+    $cache->valid = $time_valid = $cache->expire == Cache::PERMANENT || $cache->expire >= REQUEST_TIME;
 
-    // Check if invalidateTags() has been called with any of the entry's tags.
-    if ($cache->checksum_invalidations != $checksum['invalidations']) {
-      $cache->valid = FALSE;
+    $this->cacheTag->prepareGet($cache);
+    if ($cache->deleted) {
+      $this->delete($cache->cid);
+      return FALSE;
+    }
+
+    if ($time_valid && !$cache->valid) {
+      $this->invalidate($cache->cid);
     }
 
     if (!$allow_invalid && !$cache->valid) {
@@ -163,9 +171,9 @@ public function set($cid, $data, $expire = Cache::PERMANENT, array $tags = array
    * Actually set the cache.
    */
   protected function doSet($cid, $data, $expire, $tags) {
-    $flat_tags = $this->flattenTags($tags);
-    $deleted_tags = &drupal_static('Drupal\Core\Cache\DatabaseBackend::deletedTags', array());
-    $invalidated_tags = &drupal_static('Drupal\Core\Cache\DatabaseBackend::invalidatedTags', array());
+    $flat_tags = $this->cacheTag->flattenTags($tags);
+    $deleted_tags = &drupal_static('Drupal\Core\Cache\DatabaseTagBackend::deletedTags', array());
+    $invalidated_tags = &drupal_static('Drupal\Core\Cache\DatabaseTagBackend::invalidatedTags', array());
     // Remove tags that were already deleted or invalidated during this request
     // from the static caches so that another deletion or invalidation can
     // occur.
@@ -177,7 +185,8 @@ protected function doSet($cid, $data, $expire, $tags) {
         unset($invalidated_tags[$tag]);
       }
     }
-    $checksum = $this->checksumTags($flat_tags);
+    $checksum = $this->cacheTag->checksumTags($flat_tags, TRUE);
+
     $fields = array(
       'serialized' => 0,
       'created' => round(microtime(TRUE), 3),
@@ -205,8 +214,8 @@ protected function doSet($cid, $data, $expire, $tags) {
    * {@inheritdoc}
    */
   public function setMultiple(array $items) {
-    $deleted_tags = &drupal_static('Drupal\Core\Cache\DatabaseBackend::deletedTags', array());
-    $invalidated_tags = &drupal_static('Drupal\Core\Cache\DatabaseBackend::invalidatedTags', array());
+    $deleted_tags = &drupal_static('Drupal\Core\Cache\DatabaseTagBackend::deletedTags', array());
+    $invalidated_tags = &drupal_static('Drupal\Core\Cache\DatabaseTagBackend::invalidatedTags', array());
 
     // Use a transaction so that the database can write the changes in a single
     // commit.
@@ -227,7 +236,7 @@ public function setMultiple(array $items) {
           'tags' => array(),
         );
 
-        $flat_tags = $this->flattenTags($item['tags']);
+        $flat_tags = $this->cacheTag->flattenTags($item['tags']);
 
         // Remove tags that were already deleted or invalidated during this
         // request from the static caches so that another deletion or
@@ -241,7 +250,7 @@ public function setMultiple(array $items) {
           }
         }
 
-        $checksum = $this->checksumTags($flat_tags);
+        $checksum = $this->cacheTag->checksumTags($flat_tags, TRUE);
 
         $fields = array(
           'cid' => $cid,
@@ -304,32 +313,6 @@ public function deleteMultiple(array $cids) {
   }
 
   /**
-   * Implements Drupal\Core\Cache\CacheBackendInterface::deleteTags().
-   */
-  public function deleteTags(array $tags) {
-    $tag_cache = &drupal_static('Drupal\Core\Cache\CacheBackendInterface::tagCache', array());
-    $deleted_tags = &drupal_static('Drupal\Core\Cache\DatabaseBackend::deletedTags', array());
-    foreach ($this->flattenTags($tags) as $tag) {
-      // Only delete tags once per request unless they are written again.
-      if (isset($deleted_tags[$tag])) {
-        continue;
-      }
-      $deleted_tags[$tag] = TRUE;
-      unset($tag_cache[$tag]);
-      try {
-        $this->connection->merge('cache_tags')
-          ->insertFields(array('deletions' => 1))
-          ->expression('deletions', 'deletions + 1')
-          ->key('tag', $tag)
-          ->execute();
-      }
-      catch (\Exception $e) {
-        $this->catchException($e, 'cache_tags');
-      }
-    }
-  }
-
-  /**
    * Implements Drupal\Core\Cache\CacheBackendInterface::deleteAll().
    */
   public function deleteAll() {
@@ -373,32 +356,6 @@ public function invalidateMultiple(array $cids) {
   }
 
   /**
-   * Implements Drupal\Core\Cache\CacheBackendInterface::invalidateTags().
-   */
-  public function invalidateTags(array $tags) {
-    try {
-      $tag_cache = &drupal_static('Drupal\Core\Cache\CacheBackendInterface::tagCache', array());
-      $invalidated_tags = &drupal_static('Drupal\Core\Cache\DatabaseBackend::invalidatedTags', array());
-      foreach ($this->flattenTags($tags) as $tag) {
-        // Only invalidate tags once per request unless they are written again.
-        if (isset($invalidated_tags[$tag])) {
-          continue;
-        }
-        $invalidated_tags[$tag] = TRUE;
-        unset($tag_cache[$tag]);
-        $this->connection->merge('cache_tags')
-          ->insertFields(array('invalidations' => 1))
-          ->expression('invalidations', 'invalidations + 1')
-          ->key('tag', $tag)
-          ->execute();
-      }
-    }
-    catch (\Exception $e) {
-      $this->catchException($e, 'cache_tags');
-    }
-  }
-
-  /**
    * Implements Drupal\Core\Cache\CacheBackendInterface::invalidateAll().
    */
   public function invalidateAll() {
@@ -430,70 +387,6 @@ public function garbageCollection() {
   }
 
   /**
-   * 'Flattens' a tags array into an array of strings.
-   *
-   * @param array $tags
-   *   Associative array of tags to flatten.
-   *
-   * @return array
-   *   An indexed array of flattened tag identifiers.
-   */
-  protected function flattenTags(array $tags) {
-    if (isset($tags[0])) {
-      return $tags;
-    }
-
-    $flat_tags = array();
-    foreach ($tags as $namespace => $values) {
-      if (is_array($values)) {
-        foreach ($values as $value) {
-          $flat_tags[] = "$namespace:$value";
-        }
-      }
-      else {
-        $flat_tags[] = "$namespace:$values";
-      }
-    }
-    return $flat_tags;
-  }
-
-  /**
-   * Returns the sum total of validations for a given set of tags.
-   *
-   * @param array $tags
-   *   Array of flat tags.
-   *
-   * @return int
-   *   Sum of all invalidations.
-   *
-   * @see \Drupal\Core\Cache\DatabaseBackend::flattenTags()
-   */
-  protected function checksumTags($flat_tags) {
-    $tag_cache = &drupal_static('Drupal\Core\Cache\CacheBackendInterface::tagCache', array());
-
-    $checksum = array(
-      'invalidations' => 0,
-      'deletions' => 0,
-    );
-
-    $query_tags = array_diff($flat_tags, array_keys($tag_cache));
-    if ($query_tags) {
-      $db_tags = $this->connection->query('SELECT tag, invalidations, deletions FROM {cache_tags} WHERE tag IN (:tags)', array(':tags' => $query_tags))->fetchAllAssoc('tag', \PDO::FETCH_ASSOC);
-      $tag_cache += $db_tags;
-
-      // Fill static cache with empty objects for tags not found in the database.
-      $tag_cache += array_fill_keys(array_diff($query_tags, array_keys($db_tags)), $checksum);
-    }
-
-    foreach ($flat_tags as $tag) {
-      $checksum['invalidations'] += $tag_cache[$tag]['invalidations'];
-      $checksum['deletions'] += $tag_cache[$tag]['deletions'];
-    }
-
-    return $checksum;
-  }
-
-  /**
    * {@inheritdoc}
    */
   public function removeBin() {
diff --git a/core/lib/Drupal/Core/Cache/DatabaseBackendFactory.php b/core/lib/Drupal/Core/Cache/DatabaseBackendFactory.php
index 1d70164..9862d21 100644
--- a/core/lib/Drupal/Core/Cache/DatabaseBackendFactory.php
+++ b/core/lib/Drupal/Core/Cache/DatabaseBackendFactory.php
@@ -19,12 +19,20 @@ class DatabaseBackendFactory implements CacheFactoryInterface {
   protected $connection;
 
   /**
+   * The cache tag service.
+   *
+   * @var \Drupal\Core\Cache\CacheTagBackendInterface
+   */
+  protected $cacheTagBackend;
+
+  /**
    * Constructs the DatabaseBackendFactory object.
    *
    * @param \Drupal\Core\Database\Connection $connection
    */
-  function __construct(Connection $connection) {
+  function __construct(Connection $connection, CacheTagBackendBase $cache_tag_backend) {
     $this->connection = $connection;
+    $this->cacheTagBackend = $cache_tag_backend;
   }
 
   /**
@@ -37,7 +45,7 @@ function __construct(Connection $connection) {
    *   The cache backend object for the specified cache bin.
    */
   function get($bin) {
-    return new DatabaseBackend($this->connection, $bin);
+    return new DatabaseBackend($this->connection, $this->cacheTagBackend, $bin);
   }
 
 }
diff --git a/core/lib/Drupal/Core/Cache/DatabaseTagBackend.php b/core/lib/Drupal/Core/Cache/DatabaseTagBackend.php
new file mode 100644
index 0000000..015d86d
--- /dev/null
+++ b/core/lib/Drupal/Core/Cache/DatabaseTagBackend.php
@@ -0,0 +1,226 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Cache\DatabaseTag.
+ */
+
+namespace Drupal\Core\Cache;
+
+use Drupal\Core\Database\Connection;
+use Drupal\Core\Database\SchemaObjectExistsException;
+
+/**
+ * Class DatabaseTag.
+ */
+class DatabaseTagBackend extends CacheTagBackendBase {
+
+  /**
+   * The database connection.
+   *
+   * @var \Drupal\Core\Database\Connection
+   */
+  protected $connection;
+
+  /**
+   * Constructs a DatabaseTag object.
+   *
+   * @param \Drupal\Core\Database\Connection $connection
+   *   The database connection.
+   */
+  public function __construct(Connection $connection) {
+    $this->connection = $connection;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function invalidateTags(array $tags) {
+    $invalidated_tags = &drupal_static('Drupal\Core\Cache\DatabaseBackend::invalidatedTags', array());
+    $tag_cache = &drupal_static('Drupal\Core\Cache\CacheTagBackendInterface::tagCache', array());
+    try {
+      foreach ($this->flattenTags($tags) as $tag) {
+        // Only invalidate tags once per request unless they are written again.
+        if (isset($invalidated_tags[$tag])) {
+          continue;
+        }
+        $this->connection->merge('cache_tags')
+          ->insertFields(array('invalidations' => 1))
+          ->expression('invalidations', 'invalidations + 1')
+          ->key(array('tag' => $tag))
+          ->execute();
+
+        $invalidated_tags[$tag] = TRUE;
+        unset($tag_cache[$tag]);
+      }
+    }
+    catch (\Exception $e) {
+      if ($this->ensureBinExists()) {
+        $this->invalidateTags($tags);
+      }
+      else {
+        throw $e;
+      }
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function deleteTags(array $tags) {
+    $deleted_tags = &drupal_static('Drupal\Core\Cache\DatabaseTagBackend::deletedTags', array());
+    $tag_cache = &drupal_static('Drupal\Core\Cache\CacheTagBackendInterface::tagCache', array());
+    try {
+
+      foreach ($this->flattenTags($tags) as $tag) {
+        // Only delete tags once per request unless they are written again.
+        if (isset($deleted_tags[$tag])) {
+          continue;
+        }
+        $this->connection->merge('cache_tags')
+          ->insertFields(array('deletions' => 1))
+          ->expression('deletions', 'deletions + 1')
+          ->key(array('tag' => $tag))
+          ->execute();
+
+        $deleted_tags[$tag] = TRUE;
+        unset($tag_cache[$tag]);
+
+      }
+    }
+    catch (\Exception $e) {
+      if ($this->ensureBinExists()) {
+        $this->deleteTags($tags);
+      }
+      else {
+        throw $e;
+      }
+    }
+  }
+
+
+  /**
+   * {@inheritdoc}
+   */
+  public function checksumTags(array $tags, $set_context) {
+    $tag_cache = &drupal_static('Drupal\Core\Cache\CacheTagBackendInterface::tagCache', array());
+
+    if ($set_context) {
+      $deleted_tags = &drupal_static('Drupal\Core\Cache\DatabaseTagBackend::deletedTags', array());
+      // Remove tags that were already deleted during this request from the static
+      // cache so that another deletion for them will be correctly updated.
+      foreach ($tags as $tag) {
+        if (isset($deleted_tags[$tag])) {
+          unset($deleted_tags[$tag]);
+        }
+      }
+    }
+
+    $checksum = array(
+      'invalidations' => 0,
+      'deletions' => 0,
+    );
+
+    $query_tags = array_diff($tags, array_keys($tag_cache));
+    if ($query_tags) {
+      try {
+        $db_tags = $this->connection->query('SELECT tag, invalidations, deletions FROM {cache_tags} WHERE tag IN (:tags)', array(':tags' => $query_tags))->fetchAllAssoc('tag', \PDO::FETCH_ASSOC);
+      }
+      catch (\Exception $e) {
+        if ($this->ensureBinExists()) {
+          $db_tags = $this->connection->query('SELECT tag, invalidations, deletions FROM {cache_tags} WHERE tag IN (:tags)', array(':tags' => $query_tags))->fetchAllAssoc('tag', \PDO::FETCH_ASSOC);
+        }
+        else {
+          throw $e;
+        }
+      }
+      $tag_cache += $db_tags;
+
+      // Fill static cache with empty objects for tags not found in the database.
+      $tag_cache += array_fill_keys(array_diff($query_tags, array_keys($db_tags)), $checksum);
+    }
+
+    foreach ($tags as $tag) {
+      $checksum['invalidations'] += $tag_cache[$tag]['invalidations'];
+      $checksum['deletions'] += $tag_cache[$tag]['deletions'];
+    }
+
+    return $checksum;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function prepareGet(&$item) {
+    $checksum = $this->checksumTags($item->tags, FALSE);
+
+    // Check if deleteTags() has been called with any of the entry's tags.
+    $item->deleted = $item->checksum_deletions != $checksum['deletions'];
+
+    // Check if invalidateTags() has been called with any of the entry's tags.
+    if ($item->checksum_invalidations != $checksum['invalidations']) {
+      $item->valid = FALSE;
+    }
+  }
+
+  /**
+   * {@inheritdoc}.
+   */
+  public function clearCache() {
+    // Nothing to do here.
+  }
+
+  /**
+   * Check if the cache bin exists and create it if not.
+   */
+  protected function ensureBinExists() {
+    try {
+      $database_schema = $this->connection->schema();
+      if (!$database_schema->tableExists('cache_tags')) {
+        $schema_definition = $this->schemaDefinition();
+        $database_schema->createTable('cache_tags', $schema_definition['cache_tags']);
+
+        return TRUE;
+      }
+    }
+      // If another process has already created the cache table, attempting to
+      // recreate it will throw an exception. In this case just catch the
+      // exception and do nothing.
+    catch (SchemaObjectExistsException $e) {
+      return TRUE;
+    }
+    return FALSE;
+  }
+
+  /**
+   * Defines the schema for the cache bin and cache_tags table.
+   */
+  public function schemaDefinition() {
+    $schema['cache_tags'] = array(
+      'description' => 'Cache table for tracking cache tags related to the cache bin.',
+      'fields' => array(
+        'tag' => array(
+          'description' => 'Namespace-prefixed tag string.',
+          'type' => 'varchar',
+          'length' => 255,
+          'not null' => TRUE,
+          'default' => '',
+        ),
+        'invalidations' => array(
+          'description' => 'Number incremented when the tag is invalidated.',
+          'type' => 'int',
+          'not null' => TRUE,
+          'default' => 0,
+        ),
+        'deletions' => array(
+          'description' => 'Number incremented when the tag is deleted.',
+          'type' => 'int',
+          'not null' => TRUE,
+          'default' => 0,
+        ),
+      ),
+      'primary key' => array('tag'),
+    );
+    return $schema;
+  }
+}
diff --git a/core/lib/Drupal/Core/Cache/ListCacheBinsPass.php b/core/lib/Drupal/Core/Cache/ListCacheBinsPass.php
index 5381186..08c29fe 100644
--- a/core/lib/Drupal/Core/Cache/ListCacheBinsPass.php
+++ b/core/lib/Drupal/Core/Cache/ListCacheBinsPass.php
@@ -16,9 +16,7 @@
 class ListCacheBinsPass implements CompilerPassInterface {
 
   /**
-   * Implements CompilerPassInterface::process().
-   *
-   * Collects the cache bins into the cache_bins parameter.
+   * {@inheritdoc}
    */
   public function process(ContainerBuilder $container) {
     $cache_bins = array();
diff --git a/core/lib/Drupal/Core/Cache/MemoryBackend.php b/core/lib/Drupal/Core/Cache/MemoryBackend.php
index 8cd759c..a91cdc9 100644
--- a/core/lib/Drupal/Core/Cache/MemoryBackend.php
+++ b/core/lib/Drupal/Core/Cache/MemoryBackend.php
@@ -25,12 +25,23 @@ class MemoryBackend implements CacheBackendInterface {
   protected $cache = array();
 
   /**
+   * The cache tag service.
+   *
+   * @var \Drupal\Core\Cache\CacheTagBackendInterface
+   */
+  protected $cacheTag;
+
+  /**
    * Constructs a MemoryBackend object.
    *
+   *
+   * @param \Drupal\Core\Cache\CacheTagBackendInterface
+   *   The cache tag service.
    * @param string $bin
    *   The cache bin for which the object is created.
    */
-  public function __construct($bin) {
+  public function __construct(CacheTagBackendInterface $cache_tag, $bin) {
+    $this->cacheTag = $cache_tag;
   }
 
   /**
@@ -84,7 +95,17 @@ protected function prepareItem($cache, $allow_invalid) {
     }
 
     // Check expire time.
-    $cache->valid = $cache->expire == Cache::PERMANENT || $cache->expire >= REQUEST_TIME;
+    $cache->valid = $time_valid = $cache->expire == Cache::PERMANENT || $cache->expire >= REQUEST_TIME;
+
+    $this->cacheTag->prepareGet($cache);
+    if ($cache->deleted) {
+      $this->delete($cache->cid);
+      return FALSE;
+    }
+
+    if ($time_valid && !$cache->valid) {
+      $this->invalidate($cache->cid);
+    }
 
     if (!$allow_invalid && !$cache->valid) {
       return FALSE;
@@ -97,12 +118,16 @@ protected function prepareItem($cache, $allow_invalid) {
    * Implements Drupal\Core\Cache\CacheBackendInterface::set().
    */
   public function set($cid, $data, $expire = Cache::PERMANENT, array $tags = array()) {
+    $flat_tags = $this->cacheTag->flattenTags($tags);
+    $checksum = $this->cacheTag->checksumTags($flat_tags, TRUE);
     $this->cache[$cid] = (object) array(
       'cid' => $cid,
       'data' => $data,
       'created' => REQUEST_TIME,
       'expire' => $expire,
-      'tags' => $this->flattenTags($tags),
+      'tags' => $flat_tags,
+      'checksum_invalidations' => $checksum['invalidations'],
+      'checksum_deletions' => $checksum['deletions'],
     );
   }
 
@@ -130,18 +155,6 @@ public function deleteMultiple(array $cids) {
   }
 
   /**
-   * Implements Drupal\Core\Cache\CacheBackendInterface::deleteTags().
-   */
-  public function deleteTags(array $tags) {
-    $flat_tags = $this->flattenTags($tags);
-    foreach ($this->cache as $cid => $item) {
-      if (array_intersect($flat_tags, $item->tags)) {
-        unset($this->cache[$cid]);
-      }
-    }
-  }
-
-  /**
    * Implements Drupal\Core\Cache\CacheBackendInterface::deleteAll().
    */
   public function deleteAll() {
@@ -167,18 +180,6 @@ public function invalidateMultiple(array $cids) {
   }
 
   /**
-   * Implements Drupal\Core\Cache\CacheBackendInterface::invalidateTags().
-   */
-  public function invalidateTags(array $tags) {
-    $flat_tags = $this->flattenTags($tags);
-    foreach ($this->cache as $cid => $item) {
-      if (array_intersect($flat_tags, $item->tags)) {
-        $this->cache[$cid]->expire = REQUEST_TIME - 1;
-      }
-    }
-  }
-
-  /**
    * Implements Drupal\Core\Cache\CacheBackendInterface::invalidateAll().
    */
   public function invalidateAll() {
diff --git a/core/lib/Drupal/Core/Cache/MemoryBackendFactory.php b/core/lib/Drupal/Core/Cache/MemoryBackendFactory.php
index c9e288d..093b373 100644
--- a/core/lib/Drupal/Core/Cache/MemoryBackendFactory.php
+++ b/core/lib/Drupal/Core/Cache/MemoryBackendFactory.php
@@ -10,10 +10,26 @@
 class MemoryBackendFactory implements CacheFactoryInterface {
 
   /**
+   * The cache tag factory service.
+   *
+   * @var \Drupal\Core\Cache\CacheTagBackendInterface
+   */
+  protected $cacheTagBackend;
+
+  /**
+   * Constructs the DatabaseBackendFactory object.
+   *
+   * @param \Drupal\Core\Database\Connection $connection
+   */
+  function __construct(CacheTagBackendInterface $cache_tag_backend) {
+    $this->cacheTagBackend = $cache_tag_backend;
+  }
+
+  /**
    * {@inheritdoc}
    */
   function get($bin) {
-    return new MemoryBackend($bin);
+    return new MemoryBackend($this->cacheTagBackend, $bin);
   }
 
 }
diff --git a/core/lib/Drupal/Core/Cache/MemoryTagBackend.php b/core/lib/Drupal/Core/Cache/MemoryTagBackend.php
new file mode 100644
index 0000000..4920b05
--- /dev/null
+++ b/core/lib/Drupal/Core/Cache/MemoryTagBackend.php
@@ -0,0 +1,95 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Cache\MemoryTagBackend.
+ */
+
+namespace Drupal\Core\Cache;
+
+/**
+ * Class MemoryTagBackend.
+ */
+class MemoryTagBackend extends CacheTagBackendBase {
+  /**
+   * The cache tag storage.
+   *
+   * @var array
+   */
+  protected $storage = array();
+
+  /**
+   * Ensure there is an entry in storage array for a given tag.
+   *
+   * @param $tag string
+   *   Tag name.
+   */
+  protected function ensureItem($tag) {
+    if (empty($this->storage[$tag])) {
+      $this->storage[$tag] = array(
+        'invalidations' => 0,
+        'deletions' => 0,
+      );
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function invalidateTags(array $tags) {
+    foreach ($this->flattenTags($tags) as $tag) {
+      $this->ensureItem($tag);
+      $this->storage[$tag]['invalidations']++;
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function deleteTags(array $tags) {
+    foreach ($this->flattenTags($tags) as $tag) {
+      $this->ensureItem($tag);
+      $this->storage[$tag]['deletions']++;
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function checksumTags(array $tags, $set_context) {
+    $checksum = array(
+      'invalidations' => 0,
+      'deletions' => 0,
+    );
+
+    foreach ($tags as $tag) {
+      $this->ensureItem($tag);
+      $checksum['invalidations'] += $this->storage[$tag]['invalidations'];
+      $checksum['deletions'] += $this->storage[$tag]['deletions'];
+    }
+
+    return $checksum;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function prepareGet(&$item) {
+    $checksum = $this->checksumTags($item->tags, FALSE);
+
+    // Check if deleteTags() has been called with any of the entry's tags.
+    $item->deleted = $item->checksum_deletions != $checksum['deletions'];
+
+    // Check if invalidateTags() has been called with any of the entry's tags.
+    if ($item->checksum_invalidations != $checksum['invalidations']) {
+      $item->valid = FALSE;
+    }
+  }
+
+  /**
+   * {@inheritdoc}.
+   */
+  public function clearCache() {
+    // Nothing to be done here.
+  }
+}
diff --git a/core/lib/Drupal/Core/Cache/NullBackend.php b/core/lib/Drupal/Core/Cache/NullBackend.php
index d27bc13..852da7b 100644
--- a/core/lib/Drupal/Core/Cache/NullBackend.php
+++ b/core/lib/Drupal/Core/Cache/NullBackend.php
@@ -70,11 +70,6 @@ public function deleteMultiple(array $cids) {}
   public function deleteAll() {}
 
   /**
-   * Implements Drupal\Core\Cache\CacheBackendInterface::deleteTags().
-   */
-  public function deleteTags(array $tags) {}
-
-  /**
    * Implements Drupal\Core\Cache\CacheBackendInterface::invalidate().
    */
   public function invalidate($cid) {}
@@ -85,11 +80,6 @@ public function invalidate($cid) {}
   public function invalidateMultiple(array $cids) {}
 
   /**
-   * Implements Drupal\Core\Cache\CacheBackendInterface::invalidateTags().
-   */
-  public function invalidateTags(array $tags) {}
-
-  /**
    * Implements Drupal\Core\Cache\CacheBackendInterface::invalidateAll().
    */
   public function invalidateAll() {}
diff --git a/core/lib/Drupal/Core/DependencyInjection/UpdateServiceProvider.php b/core/lib/Drupal/Core/DependencyInjection/UpdateServiceProvider.php
index 32ad9b7..a2acee1 100644
--- a/core/lib/Drupal/Core/DependencyInjection/UpdateServiceProvider.php
+++ b/core/lib/Drupal/Core/DependencyInjection/UpdateServiceProvider.php
@@ -34,7 +34,11 @@ public function register(ContainerBuilder $container) {
       $container->setAlias('config.storage', 'config.storage.active');
 
       $container
-        ->register('cache_factory', 'Drupal\Core\Cache\MemoryBackendFactory');
+        ->register('cache_factory', 'Drupal\Core\Cache\MemoryBackendFactory')
+        ->addArgument(new Reference('cache_tag'));
+      $container->getDefinition('cache_tag')
+        ->setClass('Drupal\Core\Cache\MemoryTagBackend')
+        ->setArguments(array());
       $container
         ->register('router.builder', 'Drupal\Core\Routing\RouteBuilderStatic');
 
diff --git a/core/lib/Drupal/Core/Installer/InstallerServiceProvider.php b/core/lib/Drupal/Core/Installer/InstallerServiceProvider.php
index 6c393b1..d70c522 100644
--- a/core/lib/Drupal/Core/Installer/InstallerServiceProvider.php
+++ b/core/lib/Drupal/Core/Installer/InstallerServiceProvider.php
@@ -10,6 +10,7 @@
 use Drupal\Core\DependencyInjection\ContainerBuilder;
 use Drupal\Core\DependencyInjection\ServiceProviderInterface;
 use Drupal\Core\DependencyInjection\ServiceModifierInterface;
+use Symfony\Component\DependencyInjection\Reference;
 
 /**
  * Service provider for the early installer environment.
@@ -32,8 +33,11 @@ public function register(ContainerBuilder $container) {
     // Replace services with in-memory implementations.
     $definition = $container->getDefinition('cache_factory');
     $definition->setClass('Drupal\Core\Cache\MemoryBackendFactory');
-    $definition->setArguments(array());
+    $definition->setArguments(array(new Reference('cache_tag')));
     $definition->setMethodCalls(array());
+    $definition = $container->getDefinition('cache_tag');
+    $definition->setClass('Drupal\Core\Cache\MemoryTagBackend');
+    $definition->setArguments(array());
     $container
       ->register('keyvalue', 'Drupal\Core\KeyValueStore\KeyValueMemoryFactory');
     $container
diff --git a/core/modules/book/src/BookManager.php b/core/modules/book/src/BookManager.php
index c491cf4..f78a8ec 100644
--- a/core/modules/book/src/BookManager.php
+++ b/core/modules/book/src/BookManager.php
@@ -450,7 +450,7 @@ public function deleteFromBook($nid) {
     }
     $this->updateOriginalParent($original);
     $this->books = NULL;
-    \Drupal::cache('data')->deleteTags(array('bid' => $original['bid']));
+    Cache::deleteTags(array('bid' => $original['bid']));
   }
 
   /**
@@ -802,7 +802,7 @@ public function saveBookLink(array $link, $new) {
       $query->execute();
     }
     foreach ($affected_bids as $bid) {
-      \Drupal::cache('data')->deleteTags(array('bid' => $bid));
+      Cache::deleteTags(array('bid' => $bid));
     }
     return $link;
   }
diff --git a/core/modules/comment/tests/src/Entity/CommentLockTest.php b/core/modules/comment/tests/src/Entity/CommentLockTest.php
index 887d3ca..e602011 100644
--- a/core/modules/comment/tests/src/Entity/CommentLockTest.php
+++ b/core/modules/comment/tests/src/Entity/CommentLockTest.php
@@ -33,11 +33,10 @@ public static function getInfo() {
    * Test the lock behavior.
    */
   public function testLocks() {
-    $container = new ContainerBuilder();
+    $cache_tag_backend = $this->getMock('Drupal\Core\Cache\CacheTagBackendInterface');
+    $container = $this->getContainerWithCacheTags($cache_tag_backend);
     $container->set('module_handler', $this->getMock('Drupal\Core\Extension\ModuleHandlerInterface'));
     $container->set('current_user', $this->getMock('Drupal\Core\Session\AccountInterface'));
-    $container->set('cache.test', $this->getMock('Drupal\Core\Cache\CacheBackendInterface'));
-    $container->setParameter('cache_bins', array('cache.test' => 'test'));
     $container->register('request', 'Symfony\Component\HttpFoundation\Request');
     $lock = $this->getMock('Drupal\Core\Lock\LockBackendInterface');
     $cid = 2;
diff --git a/core/modules/config/src/Tests/Storage/CachedStorageTest.php b/core/modules/config/src/Tests/Storage/CachedStorageTest.php
index 766d013..87a7668 100644
--- a/core/modules/config/src/Tests/Storage/CachedStorageTest.php
+++ b/core/modules/config/src/Tests/Storage/CachedStorageTest.php
@@ -9,8 +9,8 @@
 
 use Drupal\Core\Config\FileStorage;
 use Drupal\Core\Config\CachedStorage;
-use Drupal\Core\Database\Database;
 use Drupal\Core\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Reference;
 
 /**
  * Tests CachedStorage operations.
@@ -95,7 +95,8 @@ 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());
+      ->addArgument(new Reference('database'))
+      ->addArgument(new Reference('cache_tag'));
   }
 
 }
diff --git a/core/modules/hal/src/Tests/NormalizerTestBase.php b/core/modules/hal/src/Tests/NormalizerTestBase.php
index c74854f..3ad493e 100644
--- a/core/modules/hal/src/Tests/NormalizerTestBase.php
+++ b/core/modules/hal/src/Tests/NormalizerTestBase.php
@@ -8,6 +8,7 @@
 namespace Drupal\hal\Tests;
 
 use Drupal\Core\Cache\MemoryBackend;
+use Drupal\Core\Cache\MemoryTagBackend;
 use Drupal\Core\Language\Language;
 use Drupal\hal\Encoder\JsonEncoder;
 use Drupal\hal\Normalizer\ContentEntityNormalizer;
@@ -123,7 +124,8 @@ function setUp() {
     ))->save();
 
     $entity_manager = \Drupal::entityManager();
-    $link_manager = new LinkManager(new TypeLinkManager(new MemoryBackend('default')), new RelationLinkManager(new MemoryBackend('default'), $entity_manager));
+    $cache = new MemoryBackend(new MemoryTagBackend(), 'default');
+    $link_manager = new LinkManager(new TypeLinkManager($cache), new RelationLinkManager($cache, $entity_manager));
 
     $chain_resolver = new ChainEntityResolver(array(new UuidResolver($entity_manager), new TargetIdResolver()));
 
diff --git a/core/modules/locale/src/Tests/LocaleTranslationUiTest.php b/core/modules/locale/src/Tests/LocaleTranslationUiTest.php
index fa33010..56e7605 100644
--- a/core/modules/locale/src/Tests/LocaleTranslationUiTest.php
+++ b/core/modules/locale/src/Tests/LocaleTranslationUiTest.php
@@ -143,7 +143,7 @@ function testStringTranslation() {
 
     // Reset the tag cache on the tester side in order to pick up the call to
     // Cache::deleteTags() on the tested side.
-    drupal_static_reset('Drupal\Core\Cache\CacheBackendInterface::tagCache');
+    $this->container->get('cache.tag.database')->clearCache();
 
     $this->assertTrue($name != $translation && t($name, array(), array('langcode' => $langcode)) == $translation, 't() works for non-English.');
     // Refresh the locale() cache to get fresh data from t() below. We are in
diff --git a/core/modules/simpletest/src/KernelTestBase.php b/core/modules/simpletest/src/KernelTestBase.php
index 5f0183a..4e29b14 100644
--- a/core/modules/simpletest/src/KernelTestBase.php
+++ b/core/modules/simpletest/src/KernelTestBase.php
@@ -236,8 +236,12 @@ public function containerBuild(ContainerBuilder $container) {
     // Set the default language on the minimal container.
     $this->container->setParameter('language.default_values', Language::$defaultValues);
 
+    $container->register('cache_tag', 'Drupal\Core\Cache\MemoryTagBackend');
+
     $container->register('lock', 'Drupal\Core\Lock\NullLockBackend');
-    $container->register('cache_factory', 'Drupal\Core\Cache\MemoryBackendFactory');
+    $this->settingsSet('cache', array('default' => 'cache.backend.memory'));
+    $container->register('cache_factory', 'Drupal\Core\Cache\MemoryBackendFactory')
+      ->addArgument(new Reference('cache_tag'));
 
     $container
       ->register('config.storage.active', 'Drupal\Core\Config\DatabaseStorage')
diff --git a/core/modules/simpletest/src/WebTestBase.php b/core/modules/simpletest/src/WebTestBase.php
index 4072158..4e72de2 100644
--- a/core/modules/simpletest/src/WebTestBase.php
+++ b/core/modules/simpletest/src/WebTestBase.php
@@ -867,6 +867,10 @@ protected function setUp() {
 
     // Execute the non-interactive installer.
     require_once DRUPAL_ROOT . '/core/includes/install.core.inc';
+    $this->settingsSet('cache', array('default' => 'cache.backend.memory'));
+    $this->settingsSet('cache_tag_service', 'cache.tag.memory');
+    $parameters = $this->installParameters();
+
     install_drupal($parameters);
 
     // Import new settings.php written by the installer.
@@ -1168,8 +1172,9 @@ protected function resetAll() {
    */
   protected function refreshVariables() {
     // Clear the tag cache.
-    drupal_static_reset('Drupal\Core\Cache\CacheBackendInterface::tagCache');
-    drupal_static_reset('Drupal\Core\Cache\DatabaseBackend::deletedTags');
+    $this->container->get('cache.tag.database')->clearCache();
+    drupal_static_reset('Drupal\Core\Cache\CacheTagBackendInterface::tagCache');
+    drupal_static_reset('Drupal\Core\Cache\DatabaseTagBackend::deletedTags');
     drupal_static_reset('Drupal\Core\Cache\DatabaseBackend::invalidatedTags');
 
     $this->container->get('config.factory')->reset();
diff --git a/core/modules/system/src/Tests/Cache/BackendChainUnitTest.php b/core/modules/system/src/Tests/Cache/BackendChainUnitTest.php
index 3323b1a..dc97dc4 100644
--- a/core/modules/system/src/Tests/Cache/BackendChainUnitTest.php
+++ b/core/modules/system/src/Tests/Cache/BackendChainUnitTest.php
@@ -9,6 +9,7 @@
 
 use Drupal\Core\Cache\BackendChain;
 use Drupal\Core\Cache\MemoryBackend;
+use Drupal\Core\Cache\MemoryTagBackend;
 
 /**
  * Tests BackendChain using GenericCacheBackendUnitTestBase.
@@ -27,10 +28,11 @@ protected function createCacheBackend($bin) {
     $chain = new BackendChain($bin);
 
     // We need to create some various backends in the chain.
+    $cache_tag = new MemoryTagBackend();
     $chain
-      ->appendBackend(new MemoryBackend('foo'))
-      ->prependBackend(new MemoryBackend('bar'))
-      ->appendBackend(new MemoryBackend('baz'));
+      ->appendBackend(new MemoryBackend($cache_tag, 'foo'))
+      ->prependBackend(new MemoryBackend($cache_tag, 'bar'))
+      ->appendBackend(new MemoryBackend($cache_tag, 'baz'));
 
     return $chain;
   }
diff --git a/core/modules/system/src/Tests/Cache/DatabaseBackendTagTest.php b/core/modules/system/src/Tests/Cache/DatabaseBackendTagTest.php
index 3b2b178..d72eca3 100644
--- a/core/modules/system/src/Tests/Cache/DatabaseBackendTagTest.php
+++ b/core/modules/system/src/Tests/Cache/DatabaseBackendTagTest.php
@@ -54,6 +54,9 @@ public function testTagInvalidations() {
       $this->assertTrue($bin->get('test'), 'Cache item was set in bin.');
     }
 
+    // Let's invalidate non-existing tag to create schema.
+    Cache::invalidateTags(array('create_schema' => TRUE));
+
     $invalidations_before = intval(db_select('cache_tags')->fields('cache_tags', array('invalidations'))->condition('tag', 'test_tag:2')->execute()->fetchField());
     Cache::invalidateTags(array('test_tag' => array(2)));
 
@@ -78,6 +81,9 @@ public function testTagDeletetions() {
       $this->assertTrue($bin->get('test'), 'Cache item was set in bin.');
     }
 
+    // Let's invalidate non-existing tag to create schema.
+    Cache::invalidateTags(array('create_schema' => TRUE));
+
     $deletions_before = intval(db_select('cache_tags')->fields('cache_tags', array('deletions'))->condition('tag', 'test_tag:2')->execute()->fetchField());
     Cache::deleteTags(array('test_tag' => array(2)));
 
diff --git a/core/modules/system/src/Tests/Cache/DatabaseBackendUnitTest.php b/core/modules/system/src/Tests/Cache/DatabaseBackendUnitTest.php
index 762ae86..1194db8 100644
--- a/core/modules/system/src/Tests/Cache/DatabaseBackendUnitTest.php
+++ b/core/modules/system/src/Tests/Cache/DatabaseBackendUnitTest.php
@@ -36,7 +36,7 @@ public static function getInfo() {
    *   A new DatabaseBackend object.
    */
   protected function createCacheBackend($bin) {
-    return new DatabaseBackend($this->container->get('database'), $bin);
+    return new DatabaseBackend($this->container->get('database'), $this->container->get('cache_tag'), $bin);
   }
 
 }
diff --git a/core/modules/system/src/Tests/Cache/GenericCacheBackendUnitTestBase.php b/core/modules/system/src/Tests/Cache/GenericCacheBackendUnitTestBase.php
index f6ae8f8..c305ddd 100644
--- a/core/modules/system/src/Tests/Cache/GenericCacheBackendUnitTestBase.php
+++ b/core/modules/system/src/Tests/Cache/GenericCacheBackendUnitTestBase.php
@@ -404,66 +404,6 @@ public function testDeleteMultiple() {
   }
 
   /**
-   * Tests Drupal\Core\Cache\CacheBackendInterface::deleteTags().
-   */
-  function testDeleteTags() {
-    $backend = $this->getCacheBackend();
-
-    // Create two cache entries with the same tag and tag value.
-    $backend->set('test_cid_invalidate1', $this->defaultValue, Cache::PERMANENT, array('test_tag' => 2));
-    $backend->set('test_cid_invalidate2', $this->defaultValue, Cache::PERMANENT, array('test_tag' => 2));
-    $this->assertTrue($backend->get('test_cid_invalidate1') && $backend->get('test_cid_invalidate2'), 'Two cache items were created.');
-
-    // Delete test_tag of value 1. This should delete both entries.
-    $backend->deleteTags(array('test_tag' => 2));
-    $this->assertFalse($backend->get('test_cid_invalidate1') || $backend->get('test_cid_invalidate2'), 'Two cache items invalidated after deleting a cache tag.');
-    $this->assertFalse($backend->get('test_cid_invalidate1', TRUE) || $backend->get('test_cid_invalidate2', TRUE), 'Two cache items deleted after deleting a cache tag.');
-
-    // Create two cache entries with the same tag and an array tag value.
-    $backend->set('test_cid_invalidate1', $this->defaultValue, Cache::PERMANENT, array('test_tag' => array(1)));
-    $backend->set('test_cid_invalidate2', $this->defaultValue, Cache::PERMANENT, array('test_tag' => array(1)));
-    $this->assertTrue($backend->get('test_cid_invalidate1') && $backend->get('test_cid_invalidate2'), 'Two cache items were created.');
-
-    // Delete test_tag of value 1. This should delete both entries.
-    $backend->deleteTags(array('test_tag' => array(1)));
-    $this->assertFalse($backend->get('test_cid_invalidate1') || $backend->get('test_cid_invalidate2'), 'Two cache items invalidated after deleted a cache tag.');
-    $this->assertFalse($backend->get('test_cid_invalidate1', TRUE) || $backend->get('test_cid_invalidate2', TRUE), 'Two cache items deleted after deleting a cache tag.');
-
-    // Create three cache entries with a mix of tags and tag values.
-    $backend->set('test_cid_invalidate1', $this->defaultValue, Cache::PERMANENT, array('test_tag' => array(1)));
-    $backend->set('test_cid_invalidate2', $this->defaultValue, Cache::PERMANENT, array('test_tag' => array(2)));
-    $backend->set('test_cid_invalidate3', $this->defaultValue, Cache::PERMANENT, array('test_tag_foo' => array(3)));
-    $this->assertTrue($backend->get('test_cid_invalidate1') && $backend->get('test_cid_invalidate2') && $backend->get('test_cid_invalidate3'), 'Three cached items were created.');
-    $backend->deleteTags(array('test_tag_foo' => array(3)));
-    $this->assertTrue($backend->get('test_cid_invalidate1') && $backend->get('test_cid_invalidate2'), 'Cached items not matching the tag were not deleted.');
-    $this->assertFalse($backend->get('test_cid_invalidated3', TRUE), 'Cache item matching the tag was deleted.');
-
-    // Create cache entry in multiple bins. Two cache entries
-    // (test_cid_invalidate1 and test_cid_invalidate2) still exist from previous
-    // tests.
-    $tags = array('test_tag' => array(1, 2, 3));
-    $bins = array('path', 'bootstrap', 'page');
-    foreach ($bins as $bin) {
-      $this->getCacheBackend($bin)->set('test', $this->defaultValue, Cache::PERMANENT, $tags);
-      $this->assertTrue($this->getCacheBackend($bin)->get('test'), 'Cache item was set in bin.');
-    }
-
-    // Delete tag in mulitple bins.
-    foreach ($bins as $bin) {
-      $this->getCacheBackend($bin)->deleteTags(array('test_tag' => array(2)));
-    }
-
-    // Test that cache entry has been deleted in multple bins.
-    foreach ($bins as $bin) {
-      $this->assertFalse($this->getCacheBackend($bin)->get('test', TRUE), 'Tag deletion affected item in bin.');
-    }
-    // Test that the cache entry with a matching tag has been invalidated.
-    $this->assertFalse($this->getCacheBackend($bin)->get('test_cid_invalidate2', TRUE), 'Cache items matching tag were deleted.');
-    // Test that the cache entry with without a matching tag still exists.
-    $this->assertTrue($this->getCacheBackend($bin)->get('test_cid_invalidate1'), 'Cache items not matching tag were not invalidated.');
-  }
-
-  /**
    * Test Drupal\Core\Cache\CacheBackendInterface::deleteAll().
    */
   public function testDeleteAll() {
@@ -512,66 +452,6 @@ function testInvalidate() {
   }
 
   /**
-   * Tests Drupal\Core\Cache\CacheBackendInterface::invalidateTags().
-   */
-  function testInvalidateTags() {
-    $backend = $this->getCacheBackend();
-
-    // Create two cache entries with the same tag and tag value.
-    $backend->set('test_cid_invalidate1', $this->defaultValue, Cache::PERMANENT, array('test_tag' => 2));
-    $backend->set('test_cid_invalidate2', $this->defaultValue, Cache::PERMANENT, array('test_tag' => 2));
-    $this->assertTrue($backend->get('test_cid_invalidate1') && $backend->get('test_cid_invalidate2'), 'Two cache items were created.');
-
-    // Invalidate test_tag of value 1. This should invalidate both entries.
-    $backend->invalidateTags(array('test_tag' => 2));
-    $this->assertFalse($backend->get('test_cid_invalidate1') || $backend->get('test_cid_invalidate2'), 'Two cache items invalidated after invalidating a cache tag.');
-    $this->assertTrue($backend->get('test_cid_invalidate1', TRUE) && $backend->get('test_cid_invalidate2', TRUE), 'Cache items not deleted after invalidating a cache tag.');
-
-    // Create two cache entries with the same tag and an array tag value.
-    $backend->set('test_cid_invalidate1', $this->defaultValue, Cache::PERMANENT, array('test_tag' => array(1)));
-    $backend->set('test_cid_invalidate2', $this->defaultValue, Cache::PERMANENT, array('test_tag' => array(1)));
-    $this->assertTrue($backend->get('test_cid_invalidate1') && $backend->get('test_cid_invalidate2'), 'Two cache items were created.');
-
-    // Invalidate test_tag of value 1. This should invalidate both entries.
-    $backend->invalidateTags(array('test_tag' => array(1)));
-    $this->assertFalse($backend->get('test_cid_invalidate1') || $backend->get('test_cid_invalidate2'), 'Two caches removed after invalidating a cache tag.');
-    $this->assertTrue($backend->get('test_cid_invalidate1', TRUE) && $backend->get('test_cid_invalidate2', TRUE), 'Cache items not deleted after invalidating a cache tag.');
-
-    // Create three cache entries with a mix of tags and tag values.
-    $backend->set('test_cid_invalidate1', $this->defaultValue, Cache::PERMANENT, array('test_tag' => array(1)));
-    $backend->set('test_cid_invalidate2', $this->defaultValue, Cache::PERMANENT, array('test_tag' => array(2)));
-    $backend->set('test_cid_invalidate3', $this->defaultValue, Cache::PERMANENT, array('test_tag_foo' => array(3)));
-    $this->assertTrue($backend->get('test_cid_invalidate1') && $backend->get('test_cid_invalidate2') && $backend->get('test_cid_invalidate3'), 'Three cached items were created.');
-    $backend->invalidateTags(array('test_tag_foo' => array(3)));
-    $this->assertTrue($backend->get('test_cid_invalidate1') && $backend->get('test_cid_invalidate2'), 'Cache items not matching the tag were not invalidated.');
-    $this->assertFalse($backend->get('test_cid_invalidated3'), 'Cached item matching the tag was removed.');
-
-    // Create cache entry in multiple bins. Two cache entries
-    // (test_cid_invalidate1 and test_cid_invalidate2) still exist from previous
-    // tests.
-    $tags = array('test_tag' => array(1, 2, 3));
-    $bins = array('path', 'bootstrap', 'page');
-    foreach ($bins as $bin) {
-      $this->getCacheBackend($bin)->set('test', $this->defaultValue, Cache::PERMANENT, $tags);
-      $this->assertTrue($this->getCacheBackend($bin)->get('test'), 'Cache item was set in bin.');
-    }
-
-    // Invalidate tag in mulitple bins.
-    foreach ($bins as $bin) {
-      $this->getCacheBackend($bin)->invalidateTags(array('test_tag' => array(2)));
-    }
-
-    // Test that cache entry has been invalidated in multple bins.
-    foreach ($bins as $bin) {
-      $this->assertFalse($this->getCacheBackend($bin)->get('test'), 'Tag invalidation affected item in bin.');
-    }
-    // Test that the cache entry with a matching tag has been invalidated.
-    $this->assertFalse($this->getCacheBackend($bin)->get('test_cid_invalidate2'), 'Cache items matching tag were invalidated.');
-    // Test that the cache entry with without a matching tag still exists.
-    $this->assertTrue($this->getCacheBackend($bin)->get('test_cid_invalidate1'), 'Cache items not matching tag were not invalidated.');
-  }
-
-  /**
    * Test Drupal\Core\Cache\CacheBackendInterface::invalidateAll().
    */
   public function testInvalidateAll() {
diff --git a/core/modules/system/src/Tests/Cache/MemoryBackendUnitTest.php b/core/modules/system/src/Tests/Cache/MemoryBackendUnitTest.php
index d3a29e3..f6cf75c 100644
--- a/core/modules/system/src/Tests/Cache/MemoryBackendUnitTest.php
+++ b/core/modules/system/src/Tests/Cache/MemoryBackendUnitTest.php
@@ -8,6 +8,7 @@
 namespace Drupal\system\Tests\Cache;
 
 use Drupal\Core\Cache\MemoryBackend;
+use Drupal\Core\Cache\MemoryTagBackend;
 
 /**
  * Tests MemoryBackend using GenericCacheBackendUnitTestBase.
@@ -29,6 +30,6 @@ public static function getInfo() {
    *   A new MemoryBackend object.
    */
   protected function createCacheBackend($bin) {
-    return new MemoryBackend($bin);
+    return new MemoryBackend(new MemoryTagBackend(), $bin);
   }
 }
diff --git a/core/modules/system/src/Tests/DrupalKernel/DrupalKernelSiteTest.php b/core/modules/system/src/Tests/DrupalKernel/DrupalKernelSiteTest.php
index d6f9fe8..19ae0c9 100644
--- a/core/modules/system/src/Tests/DrupalKernel/DrupalKernelSiteTest.php
+++ b/core/modules/system/src/Tests/DrupalKernel/DrupalKernelSiteTest.php
@@ -44,6 +44,7 @@ class: $class
   # Swap out a core service.
   cache.backend.database:
     class: Drupal\Core\Cache\MemoryBackendFactory
+    arguments: ['@cache_tag']
 EOD;
     file_put_contents($this->siteDirectory . '/services.yml', $doc);
 
diff --git a/core/modules/system/src/Tests/Path/AliasTest.php b/core/modules/system/src/Tests/Path/AliasTest.php
index 0e99995..e8fc981 100644
--- a/core/modules/system/src/Tests/Path/AliasTest.php
+++ b/core/modules/system/src/Tests/Path/AliasTest.php
@@ -9,6 +9,7 @@
 
 use Drupal\Core\Cache\MemoryCounterBackend;
 use Drupal\Core\Path\AliasStorage;
+use Drupal\Core\Cache\MemoryTagBackend;
 use Drupal\Core\Database\Database;
 use Drupal\Core\Path\AliasManager;
 use Drupal\Core\Path\AliasWhitelist;
@@ -165,7 +166,7 @@ function testWhitelist() {
     $connection = Database::getConnection();
     $this->fixtures->createTables($connection);
 
-    $memoryCounterBackend = new MemoryCounterBackend('default');
+    $memoryCounterBackend = new MemoryCounterBackend(new MemoryTagBackend(), 'default');
 
     // Create AliasManager and Path object.
     $aliasStorage = new AliasStorage($connection, $this->container->get('module_handler'));
diff --git a/core/modules/system/src/Tests/Plugin/CacheDecoratorTest.php b/core/modules/system/src/Tests/Plugin/CacheDecoratorTest.php
index 94ffb96..dec156b 100644
--- a/core/modules/system/src/Tests/Plugin/CacheDecoratorTest.php
+++ b/core/modules/system/src/Tests/Plugin/CacheDecoratorTest.php
@@ -8,6 +8,7 @@
 namespace Drupal\system\Tests\Plugin;
 
 use Drupal\Core\Cache\MemoryBackend;
+use Drupal\Core\Cache\MemoryTagBackend;
 use Drupal\system\Tests\Plugin\Discovery\DiscoveryTestBase;
 use Drupal\Component\Plugin\Discovery\StaticDiscovery;
 use Drupal\Core\Plugin\Discovery\CacheDecorator;
@@ -46,7 +47,7 @@ public function setUp() {
     // Use a non-db cache backend, so that we can use DiscoveryTestBase (which
     // extends UnitTestBase).
     // @todo switch to injecting the MemoryBackend http://drupal.org/node/1903346
-    \Drupal::getContainer()->set("cache.$this->cacheBin", new MemoryBackend($this->cacheBin));
+    \Drupal::getContainer()->set("cache.$this->cacheBin", new MemoryBackend(new MemoryTagBackend(), $this->cacheBin));
 
     // Create discovery objects to test.
     $this->emptyDiscovery = new StaticDiscovery();
diff --git a/core/modules/system/src/Tests/Plugin/PluginTestBase.php b/core/modules/system/src/Tests/Plugin/PluginTestBase.php
index 3a92dbd..ea709ef 100644
--- a/core/modules/system/src/Tests/Plugin/PluginTestBase.php
+++ b/core/modules/system/src/Tests/Plugin/PluginTestBase.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\system\Tests\Plugin;
 
+use Drupal\Core\Cache\MemoryTagBackend;
 use Drupal\simpletest\UnitTestBase;
 use Drupal\plugin_test\Plugin\TestPluginManager;
 use Drupal\plugin_test\Plugin\MockBlockManager;
@@ -38,7 +39,7 @@ public function setUp() {
     //   as derivatives and ReflectionFactory.
     $this->testPluginManager = new TestPluginManager();
     $this->mockBlockManager = new MockBlockManager();
-    $module_handler = new ModuleHandler(array(), new MemoryBackend('plugin'));
+    $module_handler = new ModuleHandler(array(), new MemoryBackend(new MemoryTagBackend(), 'plugin'));
     $this->defaultsTestPluginManager = new DefaultsTestPluginManager($module_handler);
 
     // The expected plugin definitions within each manager. Several tests assert
diff --git a/core/modules/views/tests/src/ViewsDataTest.php b/core/modules/views/tests/src/ViewsDataTest.php
index 2b8d25c..a3c228e 100644
--- a/core/modules/views/tests/src/ViewsDataTest.php
+++ b/core/modules/views/tests/src/ViewsDataTest.php
@@ -28,6 +28,13 @@ class ViewsDataTest extends UnitTestCase {
   protected $cacheBackend;
 
   /**
+   * The mocked cache tag backend.
+   *
+   * @var \Drupal\Core\Cache\CacheTagBackendInterface|\PHPUnit_Framework_MockObject_MockObject
+   */
+  protected $cacheTagBackend;
+
+  /**
    * The mocked module handler.
    *
    * @var \Drupal\Core\Extension\ModuleHandlerInterface|\PHPUnit_Framework_MockObject_MockObject
@@ -71,7 +78,8 @@ public static function getInfo() {
    */
   protected function setUp() {
     $this->cacheBackend = $this->getMock('Drupal\Core\Cache\CacheBackendInterface');
-    $this->getContainerWithCacheBins($this->cacheBackend);
+    $this->cacheTagBackend = $this->getMock('Drupal\Core\Cache\CacheTagBackendInterface');
+    $this->getContainerWithCacheTags($this->cacheTagBackend);
 
     $configs = array();
     $configs['views.settings']['skip_cache'] = FALSE;
@@ -222,19 +230,17 @@ public function testFullAndTableGetCache() {
       ->method('set')
       ->with("views_data:$random_table_name:en", array());
     $this->cacheBackend->expects($this->at(4))
-      ->method('deleteAll');
+      ->method('get')
+      ->with("views_data:en")
+      ->will($this->returnValue(FALSE));
     $this->cacheBackend->expects($this->at(5))
-      ->method('get')
-      ->with("views_data:en")
-      ->will($this->returnValue(FALSE));
+      ->method('set')
+      ->with("views_data:en", $expected_views_data);
     $this->cacheBackend->expects($this->at(6))
-      ->method('set')
-      ->with("views_data:en", $expected_views_data);
+      ->method('get')
+      ->with("views_data:$random_table_name:en")
+      ->will($this->returnValue(FALSE));
     $this->cacheBackend->expects($this->at(7))
-      ->method('get')
-      ->with("views_data:$random_table_name:en")
-      ->will($this->returnValue(FALSE));
-    $this->cacheBackend->expects($this->at(8))
       ->method('set')
       ->with("views_data:$random_table_name:en", array());
 
diff --git a/core/tests/Drupal/Tests/Core/Cache/BackendChainImplementationUnitTest.php b/core/tests/Drupal/Tests/Core/Cache/BackendChainImplementationUnitTest.php
index 1cf617b..32375bf 100644
--- a/core/tests/Drupal/Tests/Core/Cache/BackendChainImplementationUnitTest.php
+++ b/core/tests/Drupal/Tests/Core/Cache/BackendChainImplementationUnitTest.php
@@ -10,6 +10,7 @@
 use Drupal\Core\Cache\BackendChain;
 use Drupal\Core\Cache\Cache;
 use Drupal\Core\Cache\MemoryBackend;
+use Drupal\Core\Cache\MemoryTagBackend;
 use Drupal\Tests\UnitTestCase;
 
 /**
@@ -59,9 +60,10 @@ public function setUp() {
     parent::setUp();
 
     // Set up three memory backends to be used in the chain.
-    $this->firstBackend = new MemoryBackend('foo');
-    $this->secondBackend = new MemoryBackend('bar');
-    $this->thirdBackend = new MemoryBackend('baz');
+    $cache_tag = new MemoryTagBackend();
+    $this->firstBackend = new MemoryBackend($cache_tag, 'foo');
+    $this->secondBackend = new MemoryBackend($cache_tag, 'bar');
+    $this->thirdBackend = new MemoryBackend($cache_tag, 'baz');
 
     // Set an initial fixed dataset for all testing. The next three data
     // collections will test two edge cases (last backend has the data, and
@@ -221,83 +223,6 @@ public function testDeleteAllPropagation() {
   }
 
   /**
-   * Test that the delete tags operation is propagated to all backends
-   * in the chain.
-   */
-  public function testDeleteTagsPropagation() {
-    // Create two cache entries with the same tag and tag value.
-    $this->chain->set('test_cid_clear1', 'foo', Cache::PERMANENT, array('test_tag' => 2));
-    $this->chain->set('test_cid_clear2', 'foo', Cache::PERMANENT, array('test_tag' => 2));
-    $this->assertNotSame(FALSE, $this->firstBackend->get('test_cid_clear1')
-      && $this->firstBackend->get('test_cid_clear2')
-      && $this->secondBackend->get('test_cid_clear1')
-      && $this->secondBackend->get('test_cid_clear2')
-      && $this->thirdBackend->get('test_cid_clear1')
-      && $this->thirdBackend->get('test_cid_clear2'),
-      'Two cache items were created in all backends.');
-
-    // Invalidate test_tag of value 1. This should invalidate both entries.
-    $this->chain->deleteTags(array('test_tag' => 2));
-    $this->assertSame(FALSE, $this->firstBackend->get('test_cid_clear1')
-      && $this->firstBackend->get('test_cid_clear2')
-      && $this->secondBackend->get('test_cid_clear1')
-      && $this->secondBackend->get('test_cid_clear2')
-      && $this->thirdBackend->get('test_cid_clear1')
-      && $this->thirdBackend->get('test_cid_clear2'),
-      'Two caches removed from all backends after clearing a cache tag.');
-
-    // Create two cache entries with the same tag and an array tag value.
-    $this->chain->set('test_cid_clear1', 'foo', Cache::PERMANENT, array('test_tag' => array(1)));
-    $this->chain->set('test_cid_clear2', 'foo', Cache::PERMANENT, array('test_tag' => array(1)));
-    $this->assertNotSame(FALSE, $this->firstBackend->get('test_cid_clear1')
-      && $this->firstBackend->get('test_cid_clear2')
-      && $this->secondBackend->get('test_cid_clear1')
-      && $this->secondBackend->get('test_cid_clear2')
-      && $this->thirdBackend->get('test_cid_clear1')
-      && $this->thirdBackend->get('test_cid_clear2'),
-      'Two cache items were created in all backends.');
-
-    // Invalidate test_tag of value 1. This should invalidate both entries.
-    $this->chain->deleteTags(array('test_tag' => array(1)));
-    $this->assertSame(FALSE, $this->firstBackend->get('test_cid_clear1')
-      && $this->firstBackend->get('test_cid_clear2')
-      && $this->secondBackend->get('test_cid_clear1')
-      && $this->secondBackend->get('test_cid_clear2')
-      && $this->thirdBackend->get('test_cid_clear1')
-      && $this->thirdBackend->get('test_cid_clear2'),
-      'Two caches removed from all backends after clearing a cache tag.');
-
-    // Create three cache entries with a mix of tags and tag values.
-    $this->chain->set('test_cid_clear1', 'foo', Cache::PERMANENT, array('test_tag' => array(1)));
-    $this->chain->set('test_cid_clear2', 'foo', Cache::PERMANENT, array('test_tag' => array(2)));
-    $this->chain->set('test_cid_clear3', 'foo', Cache::PERMANENT, array('test_tag_foo' => array(3)));
-    $this->assertNotSame(FALSE, $this->firstBackend->get('test_cid_clear1')
-      && $this->firstBackend->get('test_cid_clear2')
-      && $this->firstBackend->get('test_cid_clear3')
-      && $this->secondBackend->get('test_cid_clear1')
-      && $this->secondBackend->get('test_cid_clear2')
-      && $this->secondBackend->get('test_cid_clear3')
-      && $this->thirdBackend->get('test_cid_clear1')
-      && $this->thirdBackend->get('test_cid_clear2')
-      && $this->thirdBackend->get('test_cid_clear3'),
-      'Three cached items were created in all backends.');
-
-    $this->chain->deleteTags(array('test_tag_foo' => array(3)));
-    $this->assertNotSame(FALSE, $this->firstBackend->get('test_cid_clear1')
-      && $this->firstBackend->get('test_cid_clear2')
-      && $this->secondBackend->get('test_cid_clear1')
-      && $this->secondBackend->get('test_cid_clear2')
-      && $this->thirdBackend->get('test_cid_clear1')
-      && $this->thirdBackend->get('test_cid_clear2'),
-      'Cached items not matching the tag were not cleared from any of the backends.');
-
-    $this->assertSame(FALSE, $this->firstBackend->get('test_cid_clear3')
-      && $this->secondBackend->get('test_cid_clear3')
-      && $this->thirdBackend->get('test_cid_clear3'),
-      'Cached item matching the tag was removed from all backends.');
-  }
-
-  /**
    * Test that removing bin propagates to all backends.
    */
   public function testRemoveBin() {
diff --git a/core/tests/Drupal/Tests/Core/Cache/CacheCollectorTest.php b/core/tests/Drupal/Tests/Core/Cache/CacheCollectorTest.php
index 05a987c..0b85e6d 100644
--- a/core/tests/Drupal/Tests/Core/Cache/CacheCollectorTest.php
+++ b/core/tests/Drupal/Tests/Core/Cache/CacheCollectorTest.php
@@ -27,6 +27,13 @@ class CacheCollectorTest extends UnitTestCase {
   protected $cache;
 
   /**
+   * The cache tag backend to use.
+   *
+   * @var \Drupal\Core\Cache\CacheTagBackendInterface|\PHPUnit_Framework_MockObject_MockObject
+   */
+  protected $cacheTag;
+
+  /**
    * The lock backend that should be used.
    *
    * @var \PHPUnit_Framework_MockObject_MockObject
@@ -60,11 +67,12 @@ public static function getInfo() {
    */
   protected function setUp() {
     $this->cache = $this->getMock('Drupal\Core\Cache\CacheBackendInterface');
+    $this->cacheTag = $this->getMock('Drupal\Core\Cache\CacheTagBackendInterface');
     $this->lock = $this->getMock('Drupal\Core\Lock\LockBackendInterface');
     $this->cid = $this->randomName();
     $this->collector = new CacheCollectorHelper($this->cid, $this->cache, $this->lock);
 
-    $this->getContainerWithCacheBins($this->cache);
+    $this->getContainerWithCacheTags($this->cacheTag);
   }
 
 
@@ -387,7 +395,7 @@ public function testUpdateCacheClear() {
     $this->cache->expects($this->once())
       ->method('delete')
       ->with($this->cid);
-    $this->cache->expects($this->never())
+    $this->cacheTag->expects($this->never())
       ->method('deleteTags');
     $this->collector->clear();
     $this->assertEquals($value, $this->collector->get($key));
@@ -414,7 +422,7 @@ public function testUpdateCacheClearTags() {
     // Clear the collected cache using the tags, should call it again.
     $this->cache->expects($this->never())
       ->method('delete');
-    $this->cache->expects($this->once())
+    $this->cacheTag->expects($this->once())
       ->method('deleteTags')
       ->with($tags);
     $this->collector->clear();
diff --git a/core/tests/Drupal/Tests/Core/Config/CachedStorageTest.php b/core/tests/Drupal/Tests/Core/Config/CachedStorageTest.php
index a66d55b..cd0a539 100644
--- a/core/tests/Drupal/Tests/Core/Config/CachedStorageTest.php
+++ b/core/tests/Drupal/Tests/Core/Config/CachedStorageTest.php
@@ -2,6 +2,7 @@
 
 namespace Drupal\Tests\Core\Config;
 
+use Drupal\Core\Cache\MemoryTagBackend;
 use Drupal\Tests\UnitTestCase;
 use Drupal\Core\Config\CachedStorage;
 use Drupal\Core\Cache\MemoryBackend;
@@ -63,7 +64,7 @@ public function testListAllPrimedPersistentCache() {
     $storage->expects($this->never())->method('listAll');
 
     $response = array("$prefix." . $this->randomName(), "$prefix." . $this->randomName());
-    $cache = new MemoryBackend(__FUNCTION__);
+    $cache = new MemoryBackend(new MemoryTagBackend(), __FUNCTION__);
     $cache->set('find:' . $prefix, $response);
     $this->cacheFactory->expects($this->once())
       ->method('get')
@@ -91,7 +92,7 @@ public function testGetMultipleOnPrimedCache() {
     );
     $storage = $this->getMock('Drupal\Core\Config\StorageInterface');
     $storage->expects($this->never())->method('readMultiple');
-    $cache = new MemoryBackend(__FUNCTION__);
+    $cache = new MemoryBackend(new MemoryTagBackend(), __FUNCTION__);
     foreach ($configCacheValues as $key => $value) {
       $cache->set($key, $value);
     }
@@ -122,7 +123,7 @@ public function testGetMultipleOnPartiallyPrimedCache() {
         'foo' => 'bar',
       ),
     );
-    $cache = new MemoryBackend(__FUNCTION__);
+    $cache = new MemoryBackend(new MemoryTagBackend(), __FUNCTION__);
     foreach ($configCacheValues as $key => $value) {
       $cache->set($key, $value);
     }
@@ -161,7 +162,7 @@ public function testGetMultipleOnPartiallyPrimedCache() {
    */
   public function testReadNonExistentFileCacheMiss() {
     $name = 'config.does_not_exist';
-    $cache = new MemoryBackend(__FUNCTION__);
+    $cache = new MemoryBackend(new MemoryTagBackend(), __FUNCTION__);
     $storage = $this->getMock('Drupal\Core\Config\StorageInterface');
     $storage->expects($this->once())
             ->method('read')
@@ -185,7 +186,7 @@ public function testReadNonExistentFileCacheMiss() {
    */
   public function testReadNonExistentFileCached() {
     $name = 'config.does_not_exist';
-    $cache = new MemoryBackend(__FUNCTION__);
+    $cache = new MemoryBackend(new MemoryTagBackend(), __FUNCTION__);
     $cache->set($name, FALSE);
 
     $storage = $this->getMock('Drupal\Core\Config\StorageInterface');
diff --git a/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityBaseUnitTest.php b/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityBaseUnitTest.php
index 4f718fc..f473e46 100644
--- a/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityBaseUnitTest.php
+++ b/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityBaseUnitTest.php
@@ -79,11 +79,11 @@ class ConfigEntityBaseUnitTest extends UnitTestCase {
   protected $id;
 
   /**
-   * The mocked cache backend.
+   * The mocked cache tag backend.
    *
-   * @var \Drupal\Core\Cache\CacheBackendInterface|\PHPUnit_Framework_MockObject_MockObject
+   * @var \Drupal\Core\Cache\CacheTagBackendInterface|\PHPUnit_Framework_MockObject_MockObject
    */
-  protected $cacheBackend;
+  protected $cacheTagBackend;
 
   /**
    * {@inheritdoc}
@@ -127,15 +127,11 @@ public function setUp() {
       ->with('en')
       ->will($this->returnValue(new Language(array('id' => 'en'))));
 
-    $this->cacheBackend = $this->getMock('Drupal\Core\Cache\CacheBackendInterface');
-
-    $container = new ContainerBuilder();
+    $this->cacheTagBackend = $this->getMock('Drupal\Core\Cache\CacheTagBackendInterface');
+    $container = $this->getContainerWithCacheTags($this->cacheTagBackend);
     $container->set('entity.manager', $this->entityManager);
     $container->set('uuid', $this->uuid);
     $container->set('language_manager', $this->languageManager);
-    $container->set('cache.test', $this->cacheBackend);
-    $container->setParameter('cache_bins', array('cache.test' => 'test'));
-    \Drupal::setContainer($container);
 
     $this->entity = $this->getMockForAbstractClass('\Drupal\Core\Config\Entity\ConfigEntityBase', array($values, $this->entityTypeId));
   }
@@ -344,7 +340,7 @@ public function testEnable() {
    * @depends testSetStatus
    */
   public function testDisable() {
-    $this->cacheBackend->expects($this->once())
+    $this->cacheTagBackend->expects($this->once())
       ->method('invalidateTags')
       ->with(array($this->entityTypeId => array($this->id)));
 
diff --git a/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityStorageTest.php b/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityStorageTest.php
index 37019f5..f36bafb 100644
--- a/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityStorageTest.php
+++ b/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityStorageTest.php
@@ -91,11 +91,11 @@ class ConfigEntityStorageTest extends UnitTestCase {
   protected $entityManager;
 
   /**
-   * The mocked cache backend.
+   * The mocked cache tag backend.
    *
-   * @var \Drupal\Core\Cache\CacheBackendInterface|\PHPUnit_Framework_MockObject_MockObject
+   * @var \Drupal\Core\Cache\CacheTagBackendInterface|\PHPUnit_Framework_MockObject_MockObject
    */
-  protected $cacheBackend;
+  protected $cacheTagBackend;
 
   /**
    * {@inheritdoc}
@@ -165,13 +165,9 @@ protected function setUp() {
       ->with('test_entity_type')
       ->will($this->returnValue($this->entityType));
 
-    $this->cacheBackend = $this->getMock('Drupal\Core\Cache\CacheBackendInterface');
-
-    $container = new ContainerBuilder();
+    $this->cacheTagBackend = $this->getMock('Drupal\Core\Cache\CacheTagBackendInterface');
+    $container = $this->getContainerWithCacheTags($this->cacheTagBackend);
     $container->set('entity.manager', $this->entityManager);
-    $container->set('cache.test', $this->cacheBackend);
-    $container->setParameter('cache_bins', array('cache.test' => 'test'));
-    \Drupal::setContainer($container);
 
   }
 
@@ -180,7 +176,7 @@ protected function setUp() {
    * @covers ::doCreate()
    */
   public function testCreateWithPredefinedUuid() {
-    $this->cacheBackend->expects($this->never())
+    $this->cacheTagBackend->expects($this->never())
       ->method('invalidateTags');
 
     $this->moduleHandler->expects($this->at(0))
@@ -205,7 +201,7 @@ public function testCreateWithPredefinedUuid() {
    * @return \Drupal\Core\Entity\EntityInterface
    */
   public function testCreate() {
-    $this->cacheBackend->expects($this->never())
+    $this->cacheTagBackend->expects($this->never())
       ->method('invalidateTags');
 
     $this->moduleHandler->expects($this->at(0))
@@ -247,7 +243,7 @@ public function testSaveInsert(EntityInterface $entity) {
     $config_object->expects($this->once())
       ->method('save');
 
-    $this->cacheBackend->expects($this->once())
+    $this->cacheTagBackend->expects($this->once())
       ->method('invalidateTags')
       ->with(array(
         $this->entityTypeId . 's' => TRUE, // List cache tag.
@@ -306,7 +302,7 @@ public function testSaveUpdate(EntityInterface $entity) {
     $config_object->expects($this->once())
       ->method('save');
 
-    $this->cacheBackend->expects($this->once())
+    $this->cacheTagBackend->expects($this->once())
       ->method('invalidateTags')
       ->with(array(
         $this->entityTypeId . 's' => TRUE, // List cache tag.
@@ -366,7 +362,7 @@ public function testSaveRename(ConfigEntityInterface $entity) {
     $config_object->expects($this->once())
       ->method('save');
 
-    $this->cacheBackend->expects($this->once())
+    $this->cacheTagBackend->expects($this->once())
       ->method('invalidateTags')
       ->with(array(
         $this->entityTypeId . 's' => TRUE, // List cache tag.
@@ -410,7 +406,7 @@ public function testSaveRename(ConfigEntityInterface $entity) {
    * @expectedExceptionMessage The entity does not have an ID.
    */
   public function testSaveInvalid() {
-    $this->cacheBackend->expects($this->never())
+    $this->cacheTagBackend->expects($this->never())
       ->method('invalidateTags');
 
     $entity = $this->getMockEntity();
@@ -435,7 +431,7 @@ public function testSaveDuplicate() {
     $config_object->expects($this->never())
       ->method('save');
 
-    $this->cacheBackend->expects($this->never())
+    $this->cacheTagBackend->expects($this->never())
       ->method('invalidateTags');
 
     $this->configFactory->expects($this->once())
@@ -466,7 +462,7 @@ public function testSaveMismatch() {
     $config_object->expects($this->never())
       ->method('save');
 
-    $this->cacheBackend->expects($this->never())
+    $this->cacheTagBackend->expects($this->never())
       ->method('invalidateTags');
 
     $this->configFactory->expects($this->once())
@@ -499,7 +495,7 @@ public function testSaveNoMismatch() {
     $config_object->expects($this->once())
       ->method('save');
 
-    $this->cacheBackend->expects($this->once())
+    $this->cacheTagBackend->expects($this->once())
       ->method('invalidateTags')
       ->with(array(
         $this->entityTypeId . 's' => TRUE, // List cache tag.
@@ -549,7 +545,7 @@ public function testSaveChangedUuid() {
         array('id', 'foo'),
       )));
 
-    $this->cacheBackend->expects($this->never())
+    $this->cacheTagBackend->expects($this->never())
       ->method('invalidateTags');
 
     $this->configFactory->expects($this->at(1))
@@ -702,7 +698,7 @@ public function testLoadRevision() {
    * @covers ::deleteRevision()
    */
   public function testDeleteRevision() {
-    $this->cacheBackend->expects($this->never())
+    $this->cacheTagBackend->expects($this->never())
       ->method('invalidateTags');
 
     $this->assertSame(NULL, $this->entityStorage->deleteRevision(1));
@@ -728,7 +724,7 @@ public function testDelete() {
       $config_map[] = array("the_config_prefix.$id", $config_object);
     }
 
-    $this->cacheBackend->expects($this->once())
+    $this->cacheTagBackend->expects($this->once())
       ->method('invalidateTags')
       ->with(array(
         $this->entityTypeId . 's' => TRUE, // List cache tag.
@@ -777,7 +773,7 @@ public function testDeleteNothing() {
     $this->configFactory->expects($this->never())
       ->method('get');
 
-    $this->cacheBackend->expects($this->never())
+    $this->cacheTagBackend->expects($this->never())
       ->method('invalidateTags');
 
     $this->entityStorage->delete(array());
diff --git a/core/tests/Drupal/Tests/Core/Entity/EntityManagerTest.php b/core/tests/Drupal/Tests/Core/Entity/EntityManagerTest.php
index e5eeda0..879022c 100644
--- a/core/tests/Drupal/Tests/Core/Entity/EntityManagerTest.php
+++ b/core/tests/Drupal/Tests/Core/Entity/EntityManagerTest.php
@@ -67,6 +67,13 @@ class EntityManagerTest extends UnitTestCase {
   protected $cache;
 
   /**
+   * The cache tag backend to use.
+   *
+   * @var \Drupal\Core\Cache\CacheTagBackendInterface|\PHPUnit_Framework_MockObject_MockObject
+   */
+  protected $cacheTag;
+
+  /**
    * The language manager.
    *
    * @var \Drupal\Core\Language\LanguageManager|\PHPUnit_Framework_MockObject_MockObject
@@ -119,6 +126,8 @@ protected function setUp() {
 
     $this->cache = $this->getMock('Drupal\Core\Cache\CacheBackendInterface');
 
+    $this->cacheTag = $this->getMock('Drupal\Core\Cache\CacheTagBackendInterface');
+
     $this->languageManager = $this->getMock('Drupal\Core\Language\LanguageManagerInterface');
     $this->languageManager->expects($this->any())
       ->method('getCurrentLanguage')
@@ -132,7 +141,7 @@ protected function setUp() {
     $this->formBuilder = $this->getMock('Drupal\Core\Form\FormBuilderInterface');
     $this->controllerResolver = $this->getClassResolverStub();
 
-    $this->container = $this->getContainerWithCacheBins($this->cache);
+    $this->container = $this->getContainerWithCacheTags($this->cacheTag);
 
     $this->discovery = $this->getMock('Drupal\Component\Plugin\Discovery\DiscoveryInterface');
 
@@ -182,13 +191,13 @@ protected function setUpEntityManager($definitions = array()) {
    */
   public function testClearCachedDefinitions() {
     $this->setUpEntityManager();
-    $this->cache->expects($this->at(0))
+    $this->cacheTag->expects($this->at(0))
       ->method('deleteTags')
       ->with(array('entity_types' => TRUE));
-    $this->cache->expects($this->at(1))
+    $this->cacheTag->expects($this->at(1))
       ->method('deleteTags')
       ->with(array('entity_bundles' => TRUE));
-    $this->cache->expects($this->at(2))
+    $this->cacheTag->expects($this->at(2))
       ->method('deleteTags')
       ->with(array('entity_field_info' => TRUE));
 
@@ -786,7 +795,7 @@ protected function setUpEntityWithFieldDefinition($custom_invoke_all = FALSE, $f
    */
   public function testClearCachedFieldDefinitions() {
     $this->setUpEntityManager();
-    $this->cache->expects($this->once())
+    $this->cacheTag->expects($this->once())
       ->method('deleteTags')
       ->with(array('entity_field_info' => TRUE));
     $this->typedDataManager->expects($this->once())
@@ -802,7 +811,7 @@ public function testClearCachedFieldDefinitions() {
    */
   public function testClearCachedBundles() {
     $this->setUpEntityManager();
-    $this->cache->expects($this->once())
+    $this->cacheTag->expects($this->once())
       ->method('deleteTags')
       ->with(array('entity_bundles' => TRUE));
 
@@ -888,16 +897,16 @@ public function testGetAllBundleInfo() {
     $this->cache->expects($this->at(3))
       ->method('set')
       ->with("entity_bundle_info:en");
-    $this->cache->expects($this->at(4))
+    $this->cacheTag->expects($this->at(0))
       ->method('deleteTags')
       ->with(array('entity_types' => TRUE));
-    $this->cache->expects($this->at(5))
+    $this->cacheTag->expects($this->at(1))
       ->method('deleteTags')
       ->with(array('entity_bundles' => TRUE));
-    $this->cache->expects($this->at(6))
+    $this->cacheTag->expects($this->at(2))
       ->method('deleteTags')
       ->with(array('entity_field_info' => TRUE));
-    $this->cache->expects($this->at(7))
+    $this->cache->expects($this->at(4))
       ->method('get')
       ->with("entity_bundle_info:en", FALSE)
       ->will($this->returnValue((object) array('data' => 'cached data')));
diff --git a/core/tests/Drupal/Tests/Core/Entity/EntityUnitTest.php b/core/tests/Drupal/Tests/Core/Entity/EntityUnitTest.php
index 3ecc8de..2110ddb 100644
--- a/core/tests/Drupal/Tests/Core/Entity/EntityUnitTest.php
+++ b/core/tests/Drupal/Tests/Core/Entity/EntityUnitTest.php
@@ -71,11 +71,11 @@ class EntityUnitTest extends UnitTestCase {
   protected $languageManager;
 
   /**
-   * The mocked cache backend.
+   * The mocked cache tag backend.
    *
-   * @var \Drupal\Core\Cache\CacheBackendInterface|\PHPUnit_Framework_MockObject_MockObject
+   * @var \Drupal\Core\Cache\CacheTagBackendInterface|\PHPUnit_Framework_MockObject_MockObject
    */
-  protected $cacheBackend;
+  protected $cacheTagBackend;
 
   /**
    * The entity values.
@@ -122,15 +122,11 @@ public function setUp() {
       ->with('en')
       ->will($this->returnValue(new Language(array('id' => 'en'))));
 
-    $this->cacheBackend = $this->getMock('Drupal\Core\Cache\CacheBackendInterface');
-
-    $container = new ContainerBuilder();
+    $this->cacheTagBackend = $this->getMock('Drupal\Core\Cache\CacheTagBackendInterface');
+    $container = $this->getContainerWithCacheTags($this->cacheTagBackend);
     $container->set('entity.manager', $this->entityManager);
     $container->set('uuid', $this->uuid);
     $container->set('language_manager', $this->languageManager);
-    $container->set('cache.test', $this->cacheBackend);
-    $container->setParameter('cache_bins', array('cache.test' => 'test'));
-    \Drupal::setContainer($container);
 
     $this->entity = $this->getMockForAbstractClass('\Drupal\Core\Entity\Entity', array($this->values, $this->entityTypeId));
   }
@@ -549,12 +545,12 @@ public function testPreSave() {
    * @covers ::postSave
    */
   public function testPostSave() {
-    $this->cacheBackend->expects($this->at(0))
+    $this->cacheTagBackend->expects($this->at(0))
       ->method('invalidateTags')
       ->with(array(
         $this->entityTypeId . 's' => TRUE, // List cache tag.
       ));
-    $this->cacheBackend->expects($this->at(1))
+    $this->cacheTagBackend->expects($this->at(1))
       ->method('invalidateTags')
       ->with(array(
         $this->entityTypeId . 's' => TRUE, // List cache tag.
@@ -603,7 +599,7 @@ public function testPreDelete() {
    * @covers ::postDelete
    */
   public function testPostDelete() {
-    $this->cacheBackend->expects($this->once())
+    $this->cacheTagBackend->expects($this->once())
       ->method('invalidateTags')
       ->with(array(
         $this->entityTypeId => array($this->values['id']),
diff --git a/core/tests/Drupal/Tests/Core/Entity/KeyValueStore/KeyValueEntityStorageTest.php b/core/tests/Drupal/Tests/Core/Entity/KeyValueStore/KeyValueEntityStorageTest.php
index bc21d8a..a323294 100644
--- a/core/tests/Drupal/Tests/Core/Entity/KeyValueStore/KeyValueEntityStorageTest.php
+++ b/core/tests/Drupal/Tests/Core/Entity/KeyValueStore/KeyValueEntityStorageTest.php
@@ -77,6 +77,13 @@ class KeyValueEntityStorageTest extends UnitTestCase {
   protected $cacheBackend;
 
   /**
+   * The mocked cache tag backend.
+   *
+   * @var \Drupal\Core\Cache\CacheTagBackendInterface|\PHPUnit_Framework_MockObject_MockObject
+   */
+  protected $cacheTagBackend;
+
+  /**
    * {@inheritdoc}
    */
   public static function getInfo() {
@@ -120,8 +127,6 @@ protected function setUpKeyValueEntityStorage($uuid_key = 'uuid') {
       ->with('test_entity_type')
       ->will($this->returnValue($this->entityType));
 
-    $this->cacheBackend = $this->getMock('Drupal\Core\Cache\CacheBackendInterface');
-
     $this->keyValueStore = $this->getMock('Drupal\Core\KeyValueStore\KeyValueStoreInterface');
     $this->moduleHandler = $this->getMock('Drupal\Core\Extension\ModuleHandlerInterface');
     $this->uuidService = $this->getMock('Drupal\Component\Uuid\UuidInterface');
@@ -133,12 +138,10 @@ protected function setUpKeyValueEntityStorage($uuid_key = 'uuid') {
     $this->entityStorage = new KeyValueEntityStorage($this->entityType, $this->keyValueStore, $this->uuidService, $this->languageManager);
     $this->entityStorage->setModuleHandler($this->moduleHandler);
 
-    $container = new ContainerBuilder();
+    $this->cacheTagBackend = $this->getMock('Drupal\Core\Cache\CacheTagBackendInterface');
+    $container = $this->getContainerWithCacheTags($this->cacheTagBackend);
     $container->set('entity.manager', $this->entityManager);
     $container->set('language_manager', $this->languageManager);
-    $container->set('cache.test', $this->cacheBackend);
-    $container->setParameter('cache_bins', array('cache.test' => 'test'));
-    \Drupal::setContainer($container);
   }
 
   /**
diff --git a/core/tests/Drupal/Tests/Core/Extension/ThemeHandlerTest.php b/core/tests/Drupal/Tests/Core/Extension/ThemeHandlerTest.php
index 077150b..61f448d 100644
--- a/core/tests/Drupal/Tests/Core/Extension/ThemeHandlerTest.php
+++ b/core/tests/Drupal/Tests/Core/Extension/ThemeHandlerTest.php
@@ -47,6 +47,13 @@ class ThemeHandlerTest extends UnitTestCase {
   protected $state;
 
   /**
+   * The mocked cache tag service.
+   *
+   * @var \Drupal\Core\Cache\CacheTagBackendInterface|\PHPUnit_Framework_MockObject_MockObject
+   */
+  protected $cacheTag;
+
+  /**
    * The mocked config factory.
    *
    * @var \Drupal\Core\Config\ConfigFactoryInterface|\PHPUnit_Framework_MockObject_MockObject
@@ -117,8 +124,8 @@ protected function setUp() {
       ->getMock();
     $this->themeHandler = new TestThemeHandler($this->configFactory, $this->moduleHandler, $this->state, $this->infoParser, $this->configInstaller, $this->routeBuilder, $this->extensionDiscovery);
 
-    $cache_backend = $this->getMock('Drupal\Core\Cache\CacheBackendInterface');
-    $this->getContainerWithCacheBins($cache_backend);
+    //$cache_backend = $this->getMock('Drupal\Core\Cache\CacheBackendInterface');
+    //$this->getContainerWithCacheBins($cache_backend);
   }
 
   /**
diff --git a/core/tests/Drupal/Tests/Core/Plugin/DefaultPluginManagerTest.php b/core/tests/Drupal/Tests/Core/Plugin/DefaultPluginManagerTest.php
index 86cb5cc..97a37da 100644
--- a/core/tests/Drupal/Tests/Core/Plugin/DefaultPluginManagerTest.php
+++ b/core/tests/Drupal/Tests/Core/Plugin/DefaultPluginManagerTest.php
@@ -214,18 +214,23 @@ public function testDefaultPluginManagerWithFilledCache() {
    */
   public function testCacheClearWithTags() {
     $cid = $this->randomName();
-    $cache_backend = $this->getMockBuilder('Drupal\Core\Cache\MemoryBackend')
+    $memory_tag = $this->getMockBuilder('Drupal\Core\Cache\MemoryTagBackend')
       ->disableOriginalConstructor()
       ->getMock();
-    $cache_backend
+    $memory_tag
       ->expects($this->once())
       ->method('deleteTags')
       ->with(array('tag' => TRUE));
+
+    $cache_backend = $this->getMockBuilder('Drupal\Core\Cache\MemoryBackend')
+      ->setConstructorArgs(array($memory_tag))
+      ->disableOriginalConstructor()
+      ->getMock();
     $cache_backend
       ->expects($this->never())
       ->method('deleteMultiple');
 
-    $this->getContainerWithCacheBins($cache_backend);
+    $this->getContainerWithCacheTags($memory_tag);
 
     $language = new Language(array('id' => 'en'));
     $language_manager = $this->getMock('Drupal\Core\Language\LanguageManagerInterface');
diff --git a/core/tests/Drupal/Tests/UnitTestCase.php b/core/tests/Drupal/Tests/UnitTestCase.php
index bcefce7..1dc8b0b 100644
--- a/core/tests/Drupal/Tests/UnitTestCase.php
+++ b/core/tests/Drupal/Tests/UnitTestCase.php
@@ -9,7 +9,7 @@
 
 use Drupal\Component\Utility\Random;
 use Drupal\Component\Utility\String;
-use Drupal\Core\Cache\CacheBackendInterface;
+use Drupal\Core\Cache\CacheTagBackendInterface;
 use Drupal\Core\DependencyInjection\ContainerBuilder;
 
 /**
@@ -209,22 +209,16 @@ public function getStringTranslationStub() {
   /**
    * Sets up a container with cache bins.
    *
-   * @param \Drupal\Core\Cache\CacheBackendInterface $backend
-   *   The cache backend to set up.
+   * @param \Drupal\Core\Cache\CacheTagBackendInterface $backend
+   *   The cache tag to set up.
    *
-   * @return \Symfony\Component\DependencyInjection\ContainerInterface|\PHPUnit_Framework_MockObject_MockObject
+   * @return \Symfony\Component\DependencyInjection\ContainerBuilder
    *   The container with the cache bins set up.
    */
-  protected function getContainerWithCacheBins(CacheBackendInterface $backend) {
-    $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
-    $container->expects($this->any())
-      ->method('getParameter')
-      ->with('cache_bins')
-      ->will($this->returnValue(array('cache.test' => 'test')));
-    $container->expects($this->any())
-      ->method('get')
-      ->with('cache.test')
-      ->will($this->returnValue($backend));
+  protected function getContainerWithCacheTags(CacheTagBackendInterface $backend) {
+    $container = new ContainerBuilder();
+    $container->setParameter('cache_tags', array('cache.tag.test' => 'test'));
+    $container->set('cache.tag.test', $backend);
 
     \Drupal::setContainer($container);
     return $container;
