diff --git a/core/assets/scaffold/files/default.settings.php b/core/assets/scaffold/files/default.settings.php
index 53977afb99115cc2660816737b4cb2da80f7a8fa..2b610fdf9aeb9a736cb242f5efae3e217f73dfe9 100644
--- a/core/assets/scaffold/files/default.settings.php
+++ b/core/assets/scaffold/files/default.settings.php
@@ -633,33 +633,6 @@
 # $config['system.site']['name'] = 'My Drupal site';
 # $config['user.settings']['anonymous'] = 'Visitor';
 
-/**
- * Fast 404 pages:
- *
- * Drupal can generate fully themed 404 pages. However, some of these responses
- * are for images or other resource files that are not displayed to the user.
- * This can waste bandwidth, and also generate server load.
- *
- * The options below return a simple, fast 404 page for URLs matching a
- * specific pattern:
- * - $config['system.performance']['fast_404']['exclude_paths']: A regular
- *   expression to match paths to exclude, such as images generated by image
- *   styles, or dynamically-resized images. The default pattern provided below
- *   also excludes the private file system. If you need to add more paths, you
- *   can add '|path' to the expression.
- * - $config['system.performance']['fast_404']['paths']: A regular expression to
- *   match paths that should return a simple 404 page, rather than the fully
- *   themed 404 page. If you don't have any aliases ending in htm or html you
- *   can add '|s?html?' to the expression.
- * - $config['system.performance']['fast_404']['html']: The html to return for
- *   simple 404 pages.
- *
- * Remove the leading hash signs if you would like to alter this functionality.
- */
-# $config['system.performance']['fast_404']['exclude_paths'] = '/\/(?:styles)|(?:system\/files)\//';
-# $config['system.performance']['fast_404']['paths'] = '/\.(?:txt|png|gif|jpe?g|css|js|ico|swf|flv|cgi|bat|pl|dll|exe|asp)$/i';
-# $config['system.performance']['fast_404']['html'] = '<!DOCTYPE html><html><head><title>404 Not Found</title></head><body><h1>Not Found</h1><p>The requested URL "@path" was not found on this server.</p></body></html>';
-
 /**
  * Load services definition file.
  */
diff --git a/core/core.services.yml b/core/core.services.yml
index 12440da791895d0d83dae6f86c799c22da33f575..4d178eb5f9396eadb3c26c102e975d658be240d0 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -1299,7 +1299,7 @@ services:
     class: Drupal\Core\EventSubscriber\Fast404ExceptionHtmlSubscriber
     tags:
       - { name: event_subscriber }
-    arguments: ['@config.factory', '@http_kernel']
+    arguments: ['@config.factory', '@cache_tags.invalidator']
   exception.enforced_form_response:
     class: Drupal\Core\EventSubscriber\EnforcedFormResponseSubscriber
     tags:
diff --git a/core/lib/Drupal/Core/EventSubscriber/Fast404ExceptionHtmlSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/Fast404ExceptionHtmlSubscriber.php
index 61159e979450377d3c7352e47a0d01a7c607c743..bd9594ab0528fca859ed96306ef3c748347cd3b6 100644
--- a/core/lib/Drupal/Core/EventSubscriber/Fast404ExceptionHtmlSubscriber.php
+++ b/core/lib/Drupal/Core/EventSubscriber/Fast404ExceptionHtmlSubscriber.php
@@ -2,45 +2,61 @@
 
 namespace Drupal\Core\EventSubscriber;
 
-use Drupal\Core\Config\ConfigFactoryInterface;
 use Drupal\Component\Utility\Html;
+use Drupal\Core\Cache\CacheTagsInvalidatorInterface;
+use Drupal\Core\Config\ConfigCrudEvent;
+use Drupal\Core\Config\ConfigEvents;
+use Drupal\Core\Config\ConfigFactoryInterface;
+use Drupal\Core\Render\HtmlResponse;
 use Symfony\Component\HttpFoundation\Response;
 use Symfony\Component\HttpKernel\Event\ExceptionEvent;
-use Symfony\Component\HttpKernel\HttpKernelInterface;
 
 /**
  * High-performance 404 exception subscriber.
  *
  * This subscriber will return a minimalist 404 response for HTML requests
  * without running a full page theming operation.
+ *
+ * Fast 404s are configured using the system.performance configuration object.
+ * There are the following options:
+ * - system.performance:fast_404.exclude_paths: A regular expression to match
+ *   paths to exclude, such as images generated by image styles, or
+ *   dynamically-resized images. The default pattern provided below also
+ *   excludes the private file system. If you need to add more paths, you can
+ *   add '|path' to the expression.
+ * - system.performance:fast_404.paths: A regular expression to match paths that
+ *   should return a simple 404 page, rather than the fully themed 404 page. If
+ *   you don't have any aliases ending in htm or html you can add '|s?html?' to
+ *   the expression.
+ * - system.performance:fast_404.html: The html to return for simple 404 pages.
  */
 class Fast404ExceptionHtmlSubscriber extends HttpExceptionSubscriberBase {
 
   /**
-   * The HTTP kernel.
+   * The config factory.
    *
-   * @var \Symfony\Component\HttpKernel\HttpKernelInterface
+   * @var \Drupal\Core\Config\ConfigFactoryInterface
    */
-  protected $httpKernel;
+  protected $configFactory;
 
   /**
-   * The config factory.
+   * The cache tags invalidator.
    *
-   * @var \Drupal\Core\Config\ConfigFactoryInterface
+   * @var \Drupal\Core\Cache\CacheTagsInvalidatorInterface
    */
-  protected $configFactory;
+  protected $cacheTagsInvalidator;
 
   /**
    * Constructs a new Fast404ExceptionHtmlSubscriber.
    *
    * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
    *   The configuration factory.
-   * @param \Symfony\Component\HttpKernel\HttpKernelInterface $http_kernel
-   *   The HTTP Kernel service.
+   * @param \Drupal\Core\Cache\CacheTagsInvalidatorInterface $cache_tags_invalidator
+   *   The cache tags invalidator.
    */
-  public function __construct(ConfigFactoryInterface $config_factory, HttpKernelInterface $http_kernel) {
+  public function __construct(ConfigFactoryInterface $config_factory, CacheTagsInvalidatorInterface $cache_tags_invalidator) {
     $this->configFactory = $config_factory;
-    $this->httpKernel = $http_kernel;
+    $this->cacheTagsInvalidator = $cache_tags_invalidator;
   }
 
   /**
@@ -74,10 +90,32 @@ public function on404(ExceptionEvent $event) {
       $fast_paths = $config->get('fast_404.paths');
       if ($fast_paths && preg_match($fast_paths, $request->getPathInfo())) {
         $fast_404_html = strtr($config->get('fast_404.html'), ['@path' => Html::escape($request->getUri())]);
-        $response = new Response($fast_404_html, Response::HTTP_NOT_FOUND);
+        $response = new HtmlResponse($fast_404_html, Response::HTTP_NOT_FOUND);
         $event->setResponse($response);
       }
     }
   }
 
+  /**
+   * Invalidates 4xx-response cache tag if fast 404 config is changed.
+   *
+   * @param \Drupal\Core\Config\ConfigCrudEvent $event
+   *   The configuration event.
+   */
+  public function onConfigSave(ConfigCrudEvent $event): void {
+    $saved_config = $event->getConfig();
+    if ($saved_config->getName() === 'system.performance' && $event->isChanged('fast_404')) {
+      $this->cacheTagsInvalidator->invalidateTags(['4xx-response']);
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getSubscribedEvents(): array {
+    $events = parent::getSubscribedEvents();
+    $events[ConfigEvents::SAVE] = 'onConfigSave';
+    return $events;
+  }
+
 }
diff --git a/core/tests/Drupal/FunctionalTests/EventSubscriber/Fast404Test.php b/core/tests/Drupal/FunctionalTests/EventSubscriber/Fast404Test.php
new file mode 100644
index 0000000000000000000000000000000000000000..be6d9f42dc7f828c04fdc5e12f835966c583b38f
--- /dev/null
+++ b/core/tests/Drupal/FunctionalTests/EventSubscriber/Fast404Test.php
@@ -0,0 +1,72 @@
+<?php
+
+namespace Drupal\FunctionalTests\EventSubscriber;
+
+use Drupal\Tests\BrowserTestBase;
+
+/**
+ * Tests the fast 404 functionality.
+ *
+ * @group EventSubscriber
+ *
+ * @see \Drupal\Core\EventSubscriber\Fast404ExceptionHtmlSubscriber
+ */
+class Fast404Test extends BrowserTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected $defaultTheme = 'stark';
+
+  /**
+   * Tests the fast 404 functionality.
+   */
+  public function testFast404(): void {
+    $this->drupalGet('does-not-exist');
+    $this->assertSession()->statusCodeEquals(404);
+    // Regular 404s will contain CSS from the system module.
+    $this->assertSession()->responseContains('modules/system/css/');
+    $this->drupalGet('does-not-exist.txt');
+    $this->assertSession()->statusCodeEquals(404);
+    // Fast 404s do not have any CSS.
+    $this->assertSession()->responseNotContains('modules/system/css/');
+    $this->assertSession()->responseHeaderContains('X-Drupal-Cache', 'Miss');
+    // Fast 404s can be cached.
+    $this->drupalGet('does-not-exist.txt');
+    $this->assertSession()->statusCodeEquals(404);
+    $this->assertSession()->responseHeaderContains('X-Drupal-Cache', 'Hit');
+    $this->assertSession()->pageTextNotContains('Oops I did it again!');
+
+    // Changing configuration should invalidate the cache.
+    $this->config('system.performance')->set('fast_404.html', '<!DOCTYPE html><html><head><title>404 Not Found</title></head><body><h1>Oops I did it again!</h1><p>The requested URL "@path" was not found on this server.</p></body></html>')->save();
+    $this->drupalGet('does-not-exist.txt');
+    $this->assertSession()->responseNotContains('modules/system/css/');
+    $this->assertSession()->statusCodeEquals(404);
+    $this->assertSession()->responseHeaderContains('X-Drupal-Cache', 'Miss');
+    $this->assertSession()->pageTextContains('Oops I did it again!');
+
+    // Ensure disabling works.
+    $this->config('system.performance')->set('fast_404.enabled', FALSE)->save();
+    $this->drupalGet('does-not-exist.txt');
+    $this->assertSession()->responseContains('modules/system/css/');
+    $this->assertSession()->statusCodeEquals(404);
+    $this->assertSession()->responseHeaderContains('X-Drupal-Cache', 'Miss');
+    $this->assertSession()->pageTextNotContains('Oops I did it again!');
+
+    // Ensure settings.php can override settings.
+    $settings['config']['system.performance']['fast_404']['enabled'] = (object) [
+      'value' => TRUE,
+      'required' => TRUE,
+    ];
+    $this->writeSettings($settings);
+    // Changing settings using an override means we need to rebuild everything.
+    $this->rebuildAll();
+    $this->drupalGet('does-not-exist.txt');
+    $this->assertSession()->statusCodeEquals(404);
+    $this->assertSession()->responseNotContains('modules/system/css/');
+    // Fast 404s returned via the exception subscriber still have the
+    // X-Generator header.
+    $this->assertSession()->responseHeaderContains('X-Generator', 'Drupal');
+  }
+
+}
diff --git a/sites/default/default.settings.php b/sites/default/default.settings.php
index 53977afb99115cc2660816737b4cb2da80f7a8fa..2b610fdf9aeb9a736cb242f5efae3e217f73dfe9 100644
--- a/sites/default/default.settings.php
+++ b/sites/default/default.settings.php
@@ -633,33 +633,6 @@
 # $config['system.site']['name'] = 'My Drupal site';
 # $config['user.settings']['anonymous'] = 'Visitor';
 
-/**
- * Fast 404 pages:
- *
- * Drupal can generate fully themed 404 pages. However, some of these responses
- * are for images or other resource files that are not displayed to the user.
- * This can waste bandwidth, and also generate server load.
- *
- * The options below return a simple, fast 404 page for URLs matching a
- * specific pattern:
- * - $config['system.performance']['fast_404']['exclude_paths']: A regular
- *   expression to match paths to exclude, such as images generated by image
- *   styles, or dynamically-resized images. The default pattern provided below
- *   also excludes the private file system. If you need to add more paths, you
- *   can add '|path' to the expression.
- * - $config['system.performance']['fast_404']['paths']: A regular expression to
- *   match paths that should return a simple 404 page, rather than the fully
- *   themed 404 page. If you don't have any aliases ending in htm or html you
- *   can add '|s?html?' to the expression.
- * - $config['system.performance']['fast_404']['html']: The html to return for
- *   simple 404 pages.
- *
- * Remove the leading hash signs if you would like to alter this functionality.
- */
-# $config['system.performance']['fast_404']['exclude_paths'] = '/\/(?:styles)|(?:system\/files)\//';
-# $config['system.performance']['fast_404']['paths'] = '/\.(?:txt|png|gif|jpe?g|css|js|ico|swf|flv|cgi|bat|pl|dll|exe|asp)$/i';
-# $config['system.performance']['fast_404']['html'] = '<!DOCTYPE html><html><head><title>404 Not Found</title></head><body><h1>Not Found</h1><p>The requested URL "@path" was not found on this server.</p></body></html>';
-
 /**
  * Load services definition file.
  */