diff --git a/core/lib/Drupal/Component/HttpFoundation/SecuredRedirectResponse.php b/core/lib/Drupal/Component/HttpFoundation/SecuredRedirectResponse.php
index 77c978c..66cbf36 100644
--- a/core/lib/Drupal/Component/HttpFoundation/SecuredRedirectResponse.php
+++ b/core/lib/Drupal/Component/HttpFoundation/SecuredRedirectResponse.php
@@ -33,12 +33,19 @@
    */
   public static function createFromRedirectResponse(RedirectResponse $response) {
     $safe_response = new static($response->getTargetUrl(), $response->getStatusCode(), $response->headers->allPreserveCase());
-    $safe_response->setProtocolVersion($response->getProtocolVersion());
-    $safe_response->setCharset($response->getCharset());
+    $safe_response->fromResponse($response);
     return $safe_response;
   }
 
   /**
+   * Copies over the values from the given response.
+   */
+  protected function fromResponse(RedirectResponse $response) {
+    $this->setProtocolVersion($response->getProtocolVersion());
+    $this->setCharset($response->getCharset());
+  }
+
+  /**
    * {@inheritdoc}
    */
   public function setTargetUrl($url) {
diff --git a/core/lib/Drupal/Core/Cache/CacheableRedirectResponse.php b/core/lib/Drupal/Core/Cache/CacheableRedirectResponse.php
new file mode 100644
index 0000000..7d949ff
--- /dev/null
+++ b/core/lib/Drupal/Core/Cache/CacheableRedirectResponse.php
@@ -0,0 +1,26 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Cache\CacheableResponse.
+ */
+
+namespace Drupal\Core\Cache;
+
+use Symfony\Component\HttpFoundation\RedirectResponse;
+
+/**
+ * A RedirectResponse that contains and can expose cacheability metadata.
+ *
+ * Supports Drupal's caching concepts: cache tags for invalidation and cache
+ * contexts for variations.
+ *
+ * @see \Drupal\Core\Cache\Cache
+ * @see \Drupal\Core\Cache\CacheableMetadata
+ * @see \Drupal\Core\Cache\CacheableResponseTrait
+ */
+class CacheableRedirectResponse extends RedirectResponse implements CacheableResponseInterface {
+
+  use CacheableResponseTrait;
+
+}
diff --git a/core/lib/Drupal/Core/EventSubscriber/RedirectLeadingSlashesSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/RedirectLeadingSlashesSubscriber.php
index 51ebbc2..84bdda1 100644
--- a/core/lib/Drupal/Core/EventSubscriber/RedirectLeadingSlashesSubscriber.php
+++ b/core/lib/Drupal/Core/EventSubscriber/RedirectLeadingSlashesSubscriber.php
@@ -7,7 +7,7 @@
 
 namespace Drupal\Core\EventSubscriber;
 
-use Symfony\Component\HttpFoundation\RedirectResponse;
+use Drupal\Core\Cache\CacheableRedirectResponse;
 use Symfony\Component\HttpKernel\Event\GetResponseEvent;
 use Symfony\Component\HttpKernel\KernelEvents;
 use Symfony\Component\EventDispatcher\EventSubscriberInterface;
@@ -39,7 +39,7 @@ public function redirect(GetResponseEvent $event) {
       if ($qs) {
         $qs = '?' . $qs;
       }
-      $event->setResponse(new RedirectResponse($request->getUriForPath($path) . $qs));
+      $event->setResponse(new CacheableRedirectResponse($request->getUriForPath($path) . $qs));
     }
   }
 
diff --git a/core/lib/Drupal/Core/Routing/LocalRedirectResponse.php b/core/lib/Drupal/Core/Routing/LocalRedirectResponse.php
index d8ad719..f1c79fa 100644
--- a/core/lib/Drupal/Core/Routing/LocalRedirectResponse.php
+++ b/core/lib/Drupal/Core/Routing/LocalRedirectResponse.php
@@ -8,14 +8,33 @@
 namespace Drupal\Core\Routing;
 
 use Drupal\Component\HttpFoundation\SecuredRedirectResponse;
+use Drupal\Core\Cache\CacheableResponseInterface;
+use Drupal\Core\Cache\CacheableResponseTrait;
+use Symfony\Component\HttpFoundation\RedirectResponse;
 
 /**
  * Provides a redirect response which cannot redirect to an external URL.
  */
-class LocalRedirectResponse extends SecuredRedirectResponse {
+class LocalRedirectResponse extends SecuredRedirectResponse implements CacheableResponseInterface {
 
+  use CacheableResponseTrait;
   use LocalAwareRedirectResponseTrait {
     LocalAwareRedirectResponseTrait::isLocal as isSafe;
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  protected function fromResponse(RedirectResponse $response) {
+    parent::fromResponse($response);
+
+    $metadata = $this->getCacheableMetadata();
+    if ($response instanceof CacheableResponseInterface) {
+      $metadata->merge($response->getCacheableMetadata());
+    }
+    else {
+      $metadata->setCacheMaxAge(0);
+    }
+  }
+
 }
diff --git a/core/lib/Drupal/Core/Routing/TrustedRedirectResponse.php b/core/lib/Drupal/Core/Routing/TrustedRedirectResponse.php
index c7a43a2..b218652 100644
--- a/core/lib/Drupal/Core/Routing/TrustedRedirectResponse.php
+++ b/core/lib/Drupal/Core/Routing/TrustedRedirectResponse.php
@@ -8,14 +8,18 @@
 namespace Drupal\Core\Routing;
 
 use Drupal\Component\HttpFoundation\SecuredRedirectResponse;
+use Drupal\Core\Cache\CacheableResponseInterface;
+use Drupal\Core\Cache\CacheableResponseTrait;
+use Symfony\Component\HttpFoundation\RedirectResponse;
 
 /**
  * Provides a redirect response which contains trusted URLs.
  *
  * Use this class in case you know that you want to redirect to an external URL.
  */
-class TrustedRedirectResponse extends SecuredRedirectResponse {
+class TrustedRedirectResponse extends SecuredRedirectResponse implements CacheableResponseInterface {
 
+  use CacheableResponseTrait;
   use LocalAwareRedirectResponseTrait;
 
   /**
@@ -28,6 +32,21 @@ class TrustedRedirectResponse extends SecuredRedirectResponse {
   /**
    * {@inheritdoc}
    */
+  protected function fromResponse(RedirectResponse $response) {
+    parent::fromResponse($response);
+
+    $metadata = $this->getCacheableMetadata();
+    if ($response instanceof CacheableResponseInterface) {
+      $metadata->merge($response->getCacheableMetadata());
+    }
+    else {
+      $metadata->setCacheMaxAge(0);
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
   public function __construct($url, $status = 302, $headers = array()) {
     $this->trustedUrls[$url] = TRUE;
     parent::__construct($url, $status, $headers);
diff --git a/core/lib/Drupal/Core/Routing/UrlGeneratorTrait.php b/core/lib/Drupal/Core/Routing/UrlGeneratorTrait.php
index 5a63105..7f355b2 100644
--- a/core/lib/Drupal/Core/Routing/UrlGeneratorTrait.php
+++ b/core/lib/Drupal/Core/Routing/UrlGeneratorTrait.php
@@ -7,7 +7,7 @@
 
 namespace Drupal\Core\Routing;
 
-use Symfony\Component\HttpFoundation\RedirectResponse;
+use Drupal\Core\Cache\CacheableRedirectResponse;
 
 /**
  * Wrapper methods for the Url Generator.
@@ -35,13 +35,17 @@
    * @return string
    *   The generated URL for the given route.
    */
-  protected function url($route_name, $route_parameters = array(), $options = array()) {
-    return $this->getUrlGenerator()->generateFromRoute($route_name, $route_parameters, $options);
+  protected function url($route_name, $route_parameters = array(), $options = array(), $collect_bubbleable_metadata = FALSE) {
+    return $this->getUrlGenerator()->generateFromRoute($route_name, $route_parameters, $options, $collect_bubbleable_metadata);
   }
 
   /**
    * Returns a redirect response object for the specified route.
    *
+   * Note that responses generated by this method are cacheable by default.
+   * Calling code is responsible for adding appropriate cacheability metadata
+   * and cache dependencies respectively.
+   *
    * @param string $route_name
    *   The name of the route to which to redirect.
    * @param array $route_parameters
@@ -52,13 +56,14 @@ protected function url($route_name, $route_parameters = array(), $options = arra
    *   (optional) The HTTP redirect status code for the redirect. The default is
    *   302 Found.
    *
-   * @return \Symfony\Component\HttpFoundation\RedirectResponse
+   * @return \Drupal\Core\Cache\CacheableRedirectResponse
    *   A redirect response object that may be returned by the controller.
    */
   protected function redirect($route_name, array $route_parameters = [], array $options = [], $status = 302) {
     $options['absolute'] = TRUE;
-    $url = $this->url($route_name, $route_parameters, $options);
-    return new RedirectResponse($url, $status);
+    $url = $this->url($route_name, $route_parameters, $options, TRUE);
+    $response = new CacheableRedirectResponse($url->getGeneratedUrl(), $status);
+    return $response->addCacheableDependency($url);
   }
 
   /**
diff --git a/core/modules/locale/locale.routing.yml b/core/modules/locale/locale.routing.yml
index 593e1ff..b1710c8 100644
--- a/core/modules/locale/locale.routing.yml
+++ b/core/modules/locale/locale.routing.yml
@@ -10,6 +10,8 @@ locale.check_translation:
   path: '/admin/reports/translations/check'
   defaults:
     _controller: 'Drupal\locale\Controller\LocaleController::checkTranslation'
+  options:
+    no_cache: TRUE
   requirements:
     _permission: 'translate interface'
 
diff --git a/core/modules/node/src/Controller/NodeController.php b/core/modules/node/src/Controller/NodeController.php
index 299d253..f1dacca 100644
--- a/core/modules/node/src/Controller/NodeController.php
+++ b/core/modules/node/src/Controller/NodeController.php
@@ -80,15 +80,24 @@ public function addPage() {
       }
     }
 
+    // Ensure that the response is invalidated whenever a node type is
+    // added/removed.
+    $cache_tags = array('config:node_type_list');
+
     // Bypass the node/add listing if only one content type is available.
     if (count($content) == 1) {
       $type = array_shift($content);
-      return $this->redirect('node.add', array('node_type' => $type->id()));
+      $response = $this->redirect('node.add', array('node_type' => $type->id()));
+      $response->getCacheableMetadata()->setCacheTags($cache_tags);
+      return $response;
     }
 
     return array(
       '#theme' => 'node_add_list',
       '#content' => $content,
+      '#cache' => array(
+        '#tags' => $cache_tags,
+      ),
     );
   }
 
diff --git a/core/modules/system/system.routing.yml b/core/modules/system/system.routing.yml
index e6108ac..8aa239e 100644
--- a/core/modules/system/system.routing.yml
+++ b/core/modules/system/system.routing.yml
@@ -132,6 +132,8 @@ system.admin_compact_page:
   defaults:
     _controller: 'Drupal\system\Controller\SystemController::compactPage'
     mode: 'off'
+  options:
+    no_cache: TRUE
   requirements:
     _permission: 'access administration pages'
 
diff --git a/core/modules/user/user.routing.yml b/core/modules/user/user.routing.yml
index 6eb709f..fabcb74 100644
--- a/core/modules/user/user.routing.yml
+++ b/core/modules/user/user.routing.yml
@@ -12,6 +12,8 @@ user.logout:
     _controller: '\Drupal\user\Controller\UserController::logout'
   requirements:
     _user_is_logged_in: 'TRUE'
+  options:
+    no_cache: TRUE
 
 user.admin_index:
   path: '/admin/config/people'
@@ -138,6 +140,8 @@ user.cancel_confirm:
     hashed_pass: ''
   requirements:
     _entity_access: 'user.delete'
+  options:
+    no_cache: TRUE
 
 user.reset:
   path: '/user/reset/{uid}/{timestamp}/{hash}'
diff --git a/core/tests/Drupal/Tests/Core/Routing/UrlGeneratorTraitTest.php b/core/tests/Drupal/Tests/Core/Routing/UrlGeneratorTraitTest.php
index 2bb4466..d7d64f9 100644
--- a/core/tests/Drupal/Tests/Core/Routing/UrlGeneratorTraitTest.php
+++ b/core/tests/Drupal/Tests/Core/Routing/UrlGeneratorTraitTest.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\Tests\Core\Routing;
 
+use Drupal\Core\GeneratedUrl;
 use Drupal\Tests\UnitTestCase;
 
 /**
@@ -36,12 +37,12 @@ public function testGetUrlGenerator() {
    */
   public function testRedirect() {
     $route_name = 'some_route_name';
-    $generated_url = 'some/generated/url';
+    $generated_url = (new GeneratedUrl())->setGeneratedUrl('some/generated/url');
 
     $url_generator = $this->getMock('Drupal\Core\Routing\UrlGeneratorInterface');
     $url_generator->expects($this->once())
       ->method('generateFromRoute')
-      ->with($route_name, [], ['absolute' => TRUE])
+      ->with($route_name, [], ['absolute' => TRUE], TRUE)
       ->willReturn($generated_url);
 
     $url_generator_trait_object = $this->getMockForTrait('Drupal\Core\Routing\UrlGeneratorTrait');
@@ -52,7 +53,7 @@ public function testRedirect() {
 
     $result = $url_generator_method->invoke($url_generator_trait_object, $route_name);
     $this->assertInstanceOf('Symfony\Component\HttpFoundation\RedirectResponse', $result);
-    $this->assertSame($generated_url, $result->getTargetUrl());
+    $this->assertSame($generated_url->getGeneratedUrl(), $result->getTargetUrl());
   }
 
 }
