diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigStorageController.php b/core/lib/Drupal/Core/Config/Entity/ConfigStorageController.php
index b472b8f..8e1f3bc 100644
--- a/core/lib/Drupal/Core/Config/Entity/ConfigStorageController.php
+++ b/core/lib/Drupal/Core/Config/Entity/ConfigStorageController.php
@@ -19,6 +19,13 @@
 class ConfigStorageController implements EntityStorageControllerInterface {
 
   /**
+   * Static cache of entities.
+   *
+   * @var array
+   */
+  protected $entityCache;
+
+  /**
    * Entity type for this controller instance.
    *
    * @var string
@@ -58,6 +65,15 @@ class ConfigStorageController implements EntityStorageControllerInterface {
   protected $uuidKey = 'uuid';
 
   /**
+   * Whether this entity type should use the static cache.
+   *
+   * Set by entity info.
+   *
+   * @var boolean
+   */
+  protected $cache;
+
+  /**
    * Implements Drupal\Core\Entity\EntityStorageControllerInterface::__construct().
    *
    * Sets basic variables.
@@ -65,16 +81,26 @@ class ConfigStorageController implements EntityStorageControllerInterface {
   public function __construct($entityType) {
     $this->entityType = $entityType;
     $this->entityInfo = entity_get_info($entityType);
+    $this->entityCache = array();
     $this->hookLoadArguments = array();
     $this->idKey = $this->entityInfo['entity_keys']['id'];
+
+    // Check if the entity type supports static caching of loaded entities.
+    $this->cache = !empty($this->entityInfo['static_cache']);
   }
 
   /**
    * Implements Drupal\Core\Entity\EntityStorageControllerInterface::resetCache().
    */
   public function resetCache(array $ids = NULL) {
-    // The configuration system is fast enough and/or implements its own
-    // (advanced) caching mechanism already.
+    if (isset($ids)) {
+      foreach ($ids as $id) {
+        unset($this->entityCache[$id]);
+      }
+    }
+    else {
+      $this->entityCache = array();
+    }
   }
 
   /**
@@ -85,8 +111,19 @@ public function load(array $ids = NULL) {
 
     // Create a new variable which is either a prepared version of the $ids
     // array for later comparison with the entity cache, or FALSE if no $ids
-    // were passed.
+    // were passed. The $ids array is reduced as items are loaded from cache,
+    // and we need to know if it's empty for this reason to avoid consulting the
+    // storage when all requested entities are loaded from cache.
     $passed_ids = !empty($ids) ? array_flip($ids) : FALSE;
+    // Try to load entities from the static cache, if the entity type supports
+    // static caching.
+    if ($this->cache && $ids) {
+      $entities += $this->cacheGet($ids);
+      // If any entities were loaded, remove them from the ids still to load.
+      if ($passed_ids) {
+        $ids = array_keys(array_diff_key($passed_ids, $entities));
+      }
+    }
 
     // Load any remaining entities. This is the case if $ids is set to NULL (so
     // we load all entities).
@@ -102,13 +139,20 @@ public function load(array $ids = NULL) {
       $entities += $queried_entities;
     }
 
+    if ($this->cache) {
+      // Add entities to the cache.
+      if (!empty($queried_entities)) {
+        $this->cacheSet($queried_entities);
+      }
+    }
+
     // Ensure that the returned array is ordered the same as the original
     // $ids array if this was passed in and remove any invalid ids.
     if ($passed_ids) {
       // Remove any invalid ids from the array.
       $passed_ids = array_intersect_key($passed_ids, $entities);
       foreach ($entities as $entity) {
-        $passed_ids[$entity->{$this->idKey}] = $entity;
+        $passed_ids[$entity->id()] = $entity;
       }
       $entities = $passed_ids;
     }
@@ -159,7 +203,7 @@ public function getConfigPrefix() {
    * See Drupal\comment\CommentStorageController::buildQuery() or
    * Drupal\taxonomy\TermStorageController::buildQuery() for examples.
    *
-   * @param $ids
+   * @param array|null $ids
    *   An array of entity IDs, or NULL to load all entities.
    * @param $revision_id
    *   The ID of the revision to load, or FALSE if this query is asking for the
@@ -228,6 +272,34 @@ protected function attachLoad(&$queried_entities, $revision_id = FALSE) {
   }
 
   /**
+   * Gets entities from the static cache.
+   *
+   * @param $ids
+   *   If not empty, return entities that match these IDs.
+   *
+   * @return
+   *   Array of entities from the entity cache.
+   */
+  protected function cacheGet($ids) {
+    $entities = array();
+    // Load any available entities from the internal cache.
+    if (!empty($this->entityCache)) {
+      $entities += array_intersect_key($this->entityCache, array_flip($ids));
+    }
+    return $entities;
+  }
+
+  /**
+   * Stores entities in the static entity cache.
+   *
+   * @param $entities
+   *   Entities to store in the cache.
+   */
+  protected function cacheSet($entities) {
+    $this->entityCache += $entities;
+  }
+
+  /**
    * Implements Drupal\Core\Entity\EntityStorageControllerInterface::create().
    */
   public function create(array $values) {
@@ -271,6 +343,9 @@ public function delete(array $entities) {
         ->save();
     }
 
+    // Reset the cache as soon as the changes have been applied.
+    $this->resetCache(array_keys($ids));
+
     $this->postDelete($entities);
     foreach ($entities as $id => $entity) {
       $this->invokeHook('delete', $entity);
@@ -325,6 +400,7 @@ public function save(EntityInterface $entity) {
     if (!$is_new) {
       $return = SAVED_UPDATED;
       $config->save();
+      $this->resetCache(array($entity->id()));
       $this->postSave($entity, TRUE);
       $this->invokeHook('update', $entity);
 
@@ -334,6 +410,8 @@ public function save(EntityInterface $entity) {
     else {
       $return = SAVED_NEW;
       $config->save();
+      $this->resetCache(array());
+
       $entity->enforceIsNew(FALSE);
       $this->postSave($entity, FALSE);
       $this->invokeHook('insert', $entity);
