diff --git a/core/includes/theme.inc b/core/includes/theme.inc
index 3b156a5..3bad71e 100644
--- a/core/includes/theme.inc
+++ b/core/includes/theme.inc
@@ -13,7 +13,7 @@
 use Drupal\Component\Utility\Html;
 use Drupal\Component\Utility\SafeMarkup;
 use Drupal\Component\Utility\Unicode;
-use Drupal\Component\Utility\Xss;
+use Drupal\Core\Cache\Cache;
 use Drupal\Core\Config\Config;
 use Drupal\Core\Config\StorageException;
 use Drupal\Core\Template\Attribute;
@@ -300,7 +300,7 @@ function drupal_find_theme_templates($cache, $extension, $path) {
  * @param $theme
  *   The name of a given theme; defaults to the current theme.
  *
- * @return
+ * @return mixed|null
  *   The value of the requested setting, NULL if the setting does not exist.
  */
 function theme_get_setting($setting_name, $theme = NULL) {
@@ -313,65 +313,73 @@ function theme_get_setting($setting_name, $theme = NULL) {
   }
 
   if (empty($cache[$theme])) {
-    // Create a theme settings object.
-    $cache[$theme] = new ThemeSettings($theme);
-    // Get the global settings from configuration.
-    $cache[$theme]->setData(\Drupal::config('system.theme.global')->get());
-
-    // Get the values for the theme-specific settings from the .info.yml files
-    // of the theme and all its base themes.
-    $themes = \Drupal::service('theme_handler')->listInfo();
-    if (isset($themes[$theme])) {
-      $theme_object = $themes[$theme];
-
-      // Retrieve configured theme-specific settings, if any.
-      try {
-        if ($theme_settings = \Drupal::config($theme . '.settings')->get()) {
-          $cache[$theme]->merge($theme_settings);
+    // When asking for the global settings, $theme is an empty string.
+    $cid = 'theme_settings' . (!empty($theme) ? ".$theme" : '');
+    if ($persistent_cache = \Drupal::cache('bootstrap')->get($cid)) {
+      $cache[$theme] = $persistent_cache->data;
+    }
+    else {
+      // Create a theme settings object.
+      $cache[$theme] = new ThemeSettings($theme);
+      // Get the global settings from configuration.
+      $cache[$theme]->setData(\Drupal::config('system.theme.global')->get());
+
+      // Get the values for the theme-specific settings from the .info.yml files
+      // of the theme and all its base themes.
+      $themes = \Drupal::service('theme_handler')->listInfo();
+      if (isset($themes[$theme])) {
+        $theme_object = $themes[$theme];
+
+        // Retrieve configured theme-specific settings, if any.
+        try {
+          if ($theme_settings = \Drupal::config($theme . '.settings')->get()) {
+            $cache[$theme]->merge($theme_settings);
+          }
+        } catch (StorageException $e) {
         }
-      }
-      catch (StorageException $e) {
-      }
 
-      // If the theme does not support a particular feature, override the global
-      // setting and set the value to NULL.
-      if (!empty($theme_object->info['features'])) {
-        foreach (_system_default_theme_features() as $feature) {
-          if (!in_array($feature, $theme_object->info['features'])) {
-            $cache[$theme]->set('features.' . $feature, NULL);
+        // If the theme does not support a particular feature, override the global
+        // setting and set the value to NULL.
+        if (!empty($theme_object->info['features'])) {
+          foreach (_system_default_theme_features() as $feature) {
+            if (!in_array($feature, $theme_object->info['features'])) {
+              $cache[$theme]->set('features.' . $feature, NULL);
+            }
           }
         }
-      }
 
-      // Generate the path to the logo image.
-      if ($cache[$theme]->get('features.logo')) {
-        $logo_path = $cache[$theme]->get('logo.path');
-        if ($cache[$theme]->get('logo.use_default')) {
-          $cache[$theme]->set('logo.url', file_create_url($theme_object->getPath() . '/logo.svg'));
-        }
-        elseif ($logo_path) {
-          $cache[$theme]->set('logo.url', file_create_url($logo_path));
+        // Generate the path to the logo image.
+        if ($cache[$theme]->get('features.logo')) {
+          $logo_path = $cache[$theme]->get('logo.path');
+          if ($cache[$theme]->get('logo.use_default')) {
+            $cache[$theme]->set('logo.url', file_create_url($theme_object->getPath() . '/logo.svg'));
+          }
+          elseif ($logo_path) {
+            $cache[$theme]->set('logo.url', file_create_url($logo_path));
+          }
         }
-      }
 
-      // Generate the path to the favicon.
-      if ($cache[$theme]->get('features.favicon')) {
-        $favicon_path = $cache[$theme]->get('favicon.path');
-        if ($cache[$theme]->get('favicon.use_default')) {
-          if (file_exists($favicon = $theme_object->getPath() . '/favicon.ico')) {
-            $cache[$theme]->set('favicon.url', file_create_url($favicon));
+        // Generate the path to the favicon.
+        if ($cache[$theme]->get('features.favicon')) {
+          $favicon_path = $cache[$theme]->get('favicon.path');
+          if ($cache[$theme]->get('favicon.use_default')) {
+            if (file_exists($favicon = $theme_object->getPath() . '/favicon.ico')) {
+              $cache[$theme]->set('favicon.url', file_create_url($favicon));
+            }
+            else {
+              $cache[$theme]->set('favicon.url', file_create_url('core/misc/favicon.ico'));
+            }
+          }
+          elseif ($favicon_path) {
+            $cache[$theme]->set('favicon.url', file_create_url($favicon_path));
           }
           else {
-            $cache[$theme]->set('favicon.url', file_create_url('core/misc/favicon.ico'));
+            $cache[$theme]->set('features.favicon', FALSE);
           }
         }
-        elseif ($favicon_path) {
-          $cache[$theme]->set('favicon.url', file_create_url($favicon_path));
-        }
-        else {
-          $cache[$theme]->set('features.favicon', FALSE);
-        }
       }
+      // Store in persistent cache.
+      \Drupal::cache('bootstrap')->set($cid, $cache[$theme], Cache::PERMANENT, array('theme_settings'));
     }
   }
 
diff --git a/core/modules/system/src/EventSubscriber/ThemeSettingsSubscriber.php b/core/modules/system/src/EventSubscriber/ThemeSettingsSubscriber.php
new file mode 100644
index 0000000..1b61818
--- /dev/null
+++ b/core/modules/system/src/EventSubscriber/ThemeSettingsSubscriber.php
@@ -0,0 +1,106 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\system\EventSubscriber\ThemeSettingsSubscriber.
+ */
+
+namespace Drupal\system\EventSubscriber;
+
+use Drupal\Core\Cache\CacheBackendInterface;
+use Drupal\Core\Cache\CacheTagsInvalidatorInterface;
+use Drupal\Core\Config\ConfigCrudEvent;
+use Drupal\Core\Config\ConfigEvents;
+use Drupal\Core\Extension\ThemeHandlerInterface;
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
+
+/**
+ * Deletes the container if default language has changed.
+ */
+class ThemeSettingsSubscriber implements EventSubscriberInterface {
+
+  /**
+   * The theme handler service.
+   *
+   * @var \Drupal\Core\Extension\ThemeHandlerInterface
+   */
+  protected $themeHandler;
+
+  /**
+   * The cache tags invalidator.
+   *
+   * @var \Drupal\Core\Cache\CacheTagsInvalidatorInterface
+   */
+  protected $cacheTagsInvalidator;
+
+  /**
+   * The cache bin.
+   *
+   * @var \Drupal\Core\Cache\CacheBackendInterface
+   */
+  protected $cacheBin;
+
+  /**
+   * Constructs a new class object.
+   *
+   * @param \Drupal\Core\Extension\ThemeHandlerInterface $theme_handler
+   *    The theme handler service.
+   * @param \Drupal\Core\Cache\CacheTagsInvalidatorInterface $cache_tags_invalidator
+   *   The cache bin service.
+   * @param \Drupal\Core\Cache\CacheBackendInterface $cache_bin
+   *   The cache bin service.
+   */
+  public function __construct(ThemeHandlerInterface $theme_handler, CacheTagsInvalidatorInterface $cache_tags_invalidator, CacheBackendInterface $cache_bin) {
+    $this->themeHandler = $theme_handler;
+    $this->cacheTagsInvalidator = $cache_tags_invalidator;
+    $this->cacheBin = $cache_bin;
+  }
+
+  /**
+   * Clears the theme settings cache when a theme settings are updated/deleted.
+   *
+   * @param \Drupal\Core\Config\ConfigCrudEvent $event
+   *   The configuration event.
+   * @param string $event_name
+   *   The name of the event.
+   */
+  public function onChangeOrDelete(ConfigCrudEvent $event, $event_name) {
+    if (!$config = $event->getConfig()) {
+      return;
+    }
+    $config_key = $config->getName();
+
+    // Perform a quick check on name and exit early if the config name doesn't
+    // follow the expected pattern.
+    if (!preg_match('@^[a-z0-9_].*\.settings$|^system\.theme\.global$@', $config_key)) {
+      return;
+    }
+
+    if ($config_key == 'system.theme.global') {
+      $this->cacheTagsInvalidator->invalidateTags(['theme_settings']);
+    }
+    else {
+      // Check if the config key is theme settings key. Exit if not.
+      $keys = array_map(function ($theme) {
+        return "$theme.settings";
+      }, array_keys($this->themeHandler->listInfo()));
+      if (!in_array($config_key, $keys)) {
+        return;
+      }
+
+      list($theme, ) = explode('.', $config_key, 2);
+      $this->cacheBin->delete('theme_settings.' . $theme);
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  static function getSubscribedEvents() {
+    $events[ConfigEvents::SAVE][] = ['onChangeOrDelete'];
+    $events[ConfigEvents::DELETE][] = ['onChangeOrDelete'];
+
+    return $events;
+  }
+
+}
diff --git a/core/modules/system/system.services.yml b/core/modules/system/system.services.yml
index 29ea018..fd01780 100644
--- a/core/modules/system/system.services.yml
+++ b/core/modules/system/system.services.yml
@@ -47,3 +47,8 @@ services:
     arguments: ['@theme_handler', '@cache_tags.invalidator']
     tags:
       - { name: event_subscriber }
+  system.theme_settings_subscriber:
+    class: Drupal\system\EventSubscriber\ThemeSettingsSubscriber
+    arguments: ['@theme_handler', '@cache_tags.invalidator', '@cache.bootstrap']
+    tags:
+      - { name: event_subscriber }
