diff --git a/core/core.services.yml b/core/core.services.yml
index 1c02e0b85d..c8289d8cf0 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -936,11 +936,22 @@ services:
   method_filter:
     class: Drupal\Core\Routing\MethodFilter
     tags:
-      - { name: route_filter, priority: 1 }
+      # The HTTP method route filter must run very early: it removes any routes
+      # whose requirements do not allow the HTTP method of the current request.
+      # Throws a 405 if no routes match the current request's HTTP method.
+      # (If it runs before content_type_header_matcher, it can ensure that that
+      # only receives routes which can have a Content-Type request header.)
+      - { name: route_filter, priority: 10 }
   content_type_header_matcher:
     class: Drupal\Core\Routing\ContentTypeHeaderMatcher
     tags:
-      - { name: route_filter }
+      # The Content-Type request header route filter must run early: it removes
+      # any routes whose requirements do not allow the Content-Type request
+      # header of the current request.
+      # Throws a 415 if no routes match the Content-Type request header of the
+      # current request, or if it has no Content-Type request header.
+      # Note it does nothing for GET requests.
+      - { name: route_filter, priority: 5 }
   paramconverter_manager:
     class: Drupal\Core\ParamConverter\ParamConverterManager
     tags:
diff --git a/core/modules/dblog/src/Tests/Rest/DbLogResourceTest.php b/core/modules/dblog/src/Tests/Rest/DbLogResourceTest.php
index 44dbe99dd1..abf1030456 100644
--- a/core/modules/dblog/src/Tests/Rest/DbLogResourceTest.php
+++ b/core/modules/dblog/src/Tests/Rest/DbLogResourceTest.php
@@ -41,7 +41,7 @@ public function testWatchdog() {
     $account = $this->drupalCreateUser(['restful get dblog']);
     $this->drupalLogin($account);
 
-    $response = $this->httpRequest(Url::fromRoute('rest.dblog.GET.' . $this->defaultFormat, ['id' => $id, '_format' => $this->defaultFormat]), 'GET');
+    $response = $this->httpRequest(Url::fromRoute('rest.dblog.GET', ['id' => $id, '_format' => $this->defaultFormat]), 'GET');
     $this->assertResponse(200);
     $this->assertHeader('content-type', $this->defaultMimeType);
     $log = Json::decode($response);
@@ -50,13 +50,13 @@ public function testWatchdog() {
     $this->assertEqual($log['message'], 'Test message', 'Log message text is correct.');
 
     // Request an unknown log entry.
-    $response = $this->httpRequest(Url::fromRoute('rest.dblog.GET.' . $this->defaultFormat, ['id' => 9999, '_format' => $this->defaultFormat]), 'GET');
+    $response = $this->httpRequest(Url::fromRoute('rest.dblog.GET', ['id' => 9999, '_format' => $this->defaultFormat]), 'GET');
     $this->assertResponse(404);
     $decoded = Json::decode($response);
     $this->assertEqual($decoded['message'], 'Log entry with ID 9999 was not found', 'Response message is correct.');
 
     // Make a bad request (a true malformed request would never be a route match).
-    $response = $this->httpRequest(Url::fromRoute('rest.dblog.GET.' . $this->defaultFormat, ['id' => 0, '_format' => $this->defaultFormat]), 'GET');
+    $response = $this->httpRequest(Url::fromRoute('rest.dblog.GET', ['id' => 0, '_format' => $this->defaultFormat]), 'GET');
     $this->assertResponse(400);
     $decoded = Json::decode($response);
     $this->assertEqual($decoded['message'], 'No log entry ID was provided', 'Response message is correct.');
diff --git a/core/modules/rest/config/install/rest.settings.yml b/core/modules/rest/config/install/rest.settings.yml
index 8f70c6997d..f1f51c9e2e 100644
--- a/core/modules/rest/config/install/rest.settings.yml
+++ b/core/modules/rest/config/install/rest.settings.yml
@@ -5,3 +5,10 @@
 # @see rest_update_8203()
 # @see https://www.drupal.org/node/2664780
 bc_entity_resource_permissions: false
+bc:
+  # Before Drupal 8.5, a GET route would be created for each supported format.
+  # This was confusing and unnecessary. The old routes are still created for BC
+  # reasons. New Drupal installations opt out from this by default (hence this
+  # is set to false), existing installations opt in to it.
+  # @see rest_update_8501()
+  format_specific_get_routes: false
diff --git a/core/modules/rest/config/schema/rest.schema.yml b/core/modules/rest/config/schema/rest.schema.yml
index 98b35ae6f0..60d915e978 100644
--- a/core/modules/rest/config/schema/rest.schema.yml
+++ b/core/modules/rest/config/schema/rest.schema.yml
@@ -11,6 +11,12 @@ rest.settings:
     bc_entity_resource_permissions:
       type: boolean
       label: 'Whether the pre Drupal 8.2.x behavior of having permissions for EntityResource is enabled or not.'
+    bc:
+      type: mapping
+      mapping:
+        format_specific_get_routes:
+          type: boolean
+          label: 'Whether the pre-Drupal 8.5.x behavior of having format-specific GET routes for REST resources is enabled or not.'
 
 # Method-level granularity of REST resource configuration.
 rest_resource.method:
diff --git a/core/modules/rest/rest.install b/core/modules/rest/rest.install
index 2113b0bbc3..b08d35b749 100644
--- a/core/modules/rest/rest.install
+++ b/core/modules/rest/rest.install
@@ -120,3 +120,13 @@ function rest_update_8401() {
     }
   }
 }
+
+/**
+ * Enable BC for GET routes: continue to use format-specific GET routes.
+ */
+function rest_update_8501() {
+  $config_factory = \Drupal::configFactory();
+  $rest_settings = $config_factory->getEditable('rest.settings');
+  $rest_settings->set('bc.format_specific_get_routes', TRUE)
+    ->save(TRUE);
+}
diff --git a/core/modules/rest/rest.services.yml b/core/modules/rest/rest.services.yml
index 080a681afb..2233b378c9 100644
--- a/core/modules/rest/rest.services.yml
+++ b/core/modules/rest/rest.services.yml
@@ -28,7 +28,7 @@ services:
     arguments: ['@serializer', '@renderer', '@current_route_match']
   rest.config_subscriber:
     class: Drupal\rest\EventSubscriber\RestConfigSubscriber
-    arguments: ['@router.builder']
+    arguments: ['@router.builder', '@kernel']
     tags:
       - { name: event_subscriber }
   rest.resource.entity.post_route.subscriber:
diff --git a/core/modules/rest/src/EventSubscriber/RestConfigSubscriber.php b/core/modules/rest/src/EventSubscriber/RestConfigSubscriber.php
index d199545f92..8bbb2ff592 100644
--- a/core/modules/rest/src/EventSubscriber/RestConfigSubscriber.php
+++ b/core/modules/rest/src/EventSubscriber/RestConfigSubscriber.php
@@ -4,6 +4,7 @@
 
 use Drupal\Core\Config\ConfigCrudEvent;
 use Drupal\Core\Config\ConfigEvents;
+use Drupal\Core\DrupalKernelInterface;
 use Drupal\Core\Routing\RouteBuilderInterface;
 use Symfony\Component\EventDispatcher\EventSubscriberInterface;
 
@@ -20,13 +21,23 @@ class RestConfigSubscriber implements EventSubscriberInterface {
   protected $routerBuilder;
 
   /**
+   * The Drupal Kernel.
+   *
+   * @var \Drupal\Core\DrupalKernelInterface
+   */
+  protected $kernel;
+
+  /**
    * Constructs the RestConfigSubscriber.
    *
    * @param \Drupal\Core\Routing\RouteBuilderInterface $router_builder
    *   The router builder service.
+   * @param \Drupal\Core\DrupalKernelInterface $kernel
+   *   The Drupal Kernel.
    */
-  public function __construct(RouteBuilderInterface $router_builder) {
+  public function __construct(RouteBuilderInterface $router_builder, DrupalKernelInterface $kernel) {
     $this->routerBuilder = $router_builder;
+    $this->kernel = $kernel;
   }
 
   /**
@@ -37,8 +48,14 @@ public function __construct(RouteBuilderInterface $router_builder) {
    */
   public function onSave(ConfigCrudEvent $event) {
     $saved_config = $event->getConfig();
-    if ($saved_config->getName() === 'rest.settings' && $event->isChanged('bc_entity_resource_permissions')) {
-      $this->routerBuilder->setRebuildNeeded();
+    if ($saved_config->getName() === 'rest.settings') {
+      if ($event->isChanged('bc_entity_resource_permissions')) {
+        $this->routerBuilder->setRebuildNeeded();
+      }
+      elseif ($event->isChanged('bc.format_specific_get_routes')) {
+        $this->kernel->invalidateContainer();
+        $this->routerBuilder->setRebuildNeeded();
+      }
     }
   }
 
diff --git a/core/modules/rest/src/Plugin/ResourceBase.php b/core/modules/rest/src/Plugin/ResourceBase.php
index b40a03109b..3e803a00d7 100644
--- a/core/modules/rest/src/Plugin/ResourceBase.php
+++ b/core/modules/rest/src/Plugin/ResourceBase.php
@@ -2,6 +2,8 @@
 
 namespace Drupal\rest\Plugin;
 
+use Drupal\Core\Config\ConfigFactoryInterface;
+use Drupal\Core\Config\ImmutableConfig;
 use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
 use Drupal\Core\Plugin\PluginBase;
 use Psr\Log\LoggerInterface;
@@ -41,6 +43,13 @@
   protected $logger;
 
   /**
+   * REST settings config instance.
+   *
+   * @var \Drupal\Core\Config\ImmutableConfig
+   */
+  protected $restSettings;
+
+  /**
    * Constructs a Drupal\rest\Plugin\ResourceBase object.
    *
    * @param array $configuration
@@ -53,11 +62,14 @@
    *   The available serialization formats.
    * @param \Psr\Log\LoggerInterface $logger
    *   A logger instance.
+   * @param \Drupal\Core\Config\ImmutableConfig $rest_settings
+   *   A REST settings config instance.
    */
-  public function __construct(array $configuration, $plugin_id, $plugin_definition, array $serializer_formats, LoggerInterface $logger) {
+  public function __construct(array $configuration, $plugin_id, $plugin_definition, array $serializer_formats, LoggerInterface $logger, ImmutableConfig $rest_settings) {
     parent::__construct($configuration, $plugin_id, $plugin_definition);
     $this->serializerFormats = $serializer_formats;
     $this->logger = $logger;
+    $this->restSettings = $rest_settings;
   }
 
   /**
@@ -69,7 +81,8 @@ public static function create(ContainerInterface $container, array $configuratio
       $plugin_id,
       $plugin_definition,
       $container->getParameter('serializer.formats'),
-      $container->get('logger.factory')->get('rest')
+      $container->get('logger.factory')->get('rest'),
+      $container->get('config.factory')->get('rest.settings')
     );
   }
 
@@ -110,33 +123,30 @@ public function routes() {
       $create_path = $definition['uri_paths']['https://www.drupal.org/link-relations/create'];
     }
 
+    $rest_bc_settings = $this->restSettings->get('bc');
+
     $route_name = strtr($this->pluginId, ':', '.');
 
     $methods = $this->availableMethods();
     foreach ($methods as $method) {
-      $route = $this->getBaseRoute($canonical_path, $method);
-
-      switch ($method) {
-        case 'POST':
-          $route->setPath($create_path);
-          $collection->add("$route_name.$method", $route);
-          break;
-
-        case 'GET':
-        case 'HEAD':
-          // Restrict GET and HEAD requests to the media type specified in the
-          // HTTP Accept headers.
-          foreach ($this->serializerFormats as $format_name) {
-            // Expose one route per available format.
-            $format_route = clone $route;
-            $format_route->addRequirements(['_format' => $format_name]);
-            $collection->add("$route_name.$method.$format_name", $format_route);
-          }
-          break;
-
-        default:
-          $collection->add("$route_name.$method", $route);
-          break;
+      $path = $method === 'POST'
+        ? $create_path
+        : $canonical_path;
+      $route = $this->getBaseRoute($path, $method);
+
+      // Note that '_format' and '_content_type_format' route requirements are
+      // added in ResourceRoutes::getRoutesForResourceConfig().
+      $collection->add("$route_name.$method", $route);
+
+      // BC: the REST module originally created per-format GET routes, instead
+      // of a single route. To minimize the surface of this BC layer, this uses
+      // route definitions that are as empty as possible, plus an outbound route
+      // processor.
+      // @see \Drupal\rest\RouteProcessor\RestResourceGetRouteProcessorBC
+      if ($rest_bc_settings['format_specific_get_routes'] && ($method === 'GET' || $method === 'HEAD')) {
+        foreach ($this->serializerFormats as $format_name) {
+          $collection->add("$route_name.$method.$format_name", (new Route(''))->setOption('bc_route', TRUE));
+        }
       }
     }
 
diff --git a/core/modules/rest/src/Plugin/rest/resource/EntityResource.php b/core/modules/rest/src/Plugin/rest/resource/EntityResource.php
index 5d9849ded4..f5162eeaa6 100644
--- a/core/modules/rest/src/Plugin/rest/resource/EntityResource.php
+++ b/core/modules/rest/src/Plugin/rest/resource/EntityResource.php
@@ -52,18 +52,18 @@ class EntityResource extends ResourceBase implements DependentPluginInterface {
   protected $entityType;
 
   /**
-   * The config factory.
+   * The link relation type manager used to create HTTP header links.
    *
-   * @var \Drupal\Core\Config\ConfigFactoryInterface
+   * @var \Drupal\Component\Plugin\PluginManagerInterface
    */
-  protected $configFactory;
+  protected $linkRelationTypeManager;
 
   /**
-   * The link relation type manager used to create HTTP header links.
+   * The config factory.
    *
-   * @var \Drupal\Component\Plugin\PluginManagerInterface
+   * @var \Drupal\Core\Config\ConfigFactoryInterface
    */
-  protected $linkRelationTypeManager;
+  protected $configFactory;
 
   /**
    * Constructs a Drupal\rest\Plugin\rest\resource\EntityResource object.
@@ -86,7 +86,7 @@ class EntityResource extends ResourceBase implements DependentPluginInterface {
    *   The link relation type manager.
    */
   public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager, $serializer_formats, LoggerInterface $logger, ConfigFactoryInterface $config_factory, PluginManagerInterface $link_relation_type_manager) {
-    parent::__construct($configuration, $plugin_id, $plugin_definition, $serializer_formats, $logger);
+    parent::__construct($configuration, $plugin_id, $plugin_definition, $serializer_formats, $logger, $config_factory->get('rest.settings'));
     $this->entityType = $entity_type_manager->getDefinition($plugin_definition['entity_type']);
     $this->configFactory = $config_factory;
     $this->linkRelationTypeManager = $link_relation_type_manager;
diff --git a/core/modules/rest/src/RestServiceProvider.php b/core/modules/rest/src/RestServiceProvider.php
index e705de4177..0de4477f8b 100644
--- a/core/modules/rest/src/RestServiceProvider.php
+++ b/core/modules/rest/src/RestServiceProvider.php
@@ -2,20 +2,19 @@
 
 namespace Drupal\rest;
 
+use Drupal\Core\Config\BootstrapConfigStorageFactory;
 use Drupal\Core\DependencyInjection\ContainerBuilder;
 use Drupal\Core\DependencyInjection\ServiceProviderInterface;
 use Drupal\rest\LinkManager\LinkManager;
 use Drupal\rest\LinkManager\RelationLinkManager;
 use Drupal\rest\LinkManager\TypeLinkManager;
+use Drupal\rest\RouteProcessor\RestResourceGetRouteProcessorBC;
 use Symfony\Component\DependencyInjection\DefinitionDecorator;
+use Symfony\Component\DependencyInjection\Parameter;
 use Symfony\Component\DependencyInjection\Reference;
 
 /**
  * Provides BC services.
- *
- * These services are not added via rest.services.yml because the service
- * classes extend classes from the HAL module. They also have no use without
- * that module.
  */
 class RestServiceProvider implements ServiceProviderInterface {
 
@@ -24,6 +23,9 @@ class RestServiceProvider implements ServiceProviderInterface {
    */
   public function register(ContainerBuilder $container) {
     $modules = $container->getParameter(('container.modules'));
+
+    // BC: services moved to HAL module. Not added in rest.services.yml because
+    // the services reference services in the HAL module.
     if (isset($modules['hal'])) {
       // @deprecated in Drupal 8.3.x and will be removed before Drupal 9.0.0.
       //   Use hal.link_manager instead.
@@ -46,6 +48,16 @@ public function register(ContainerBuilder $container) {
       $service_definition->setClass(RelationLinkManager::class);
       $container->setDefinition('rest.link_manager.relation', $service_definition);
     }
+
+    // BC: outbound route processor for format-specific GET routes. Not added
+    // in rest.services.yml because its presence depends on configuration.
+    $settings = BootstrapConfigStorageFactory::get()->read('rest.settings');
+    if (!empty($settings['bc']['format_specific_get_routes'])){
+      $container->register('rest.route_processor_get_bc', RestResourceGetRouteProcessorBC::class)
+        ->addArgument(new Parameter('serializer.formats'))
+        ->addArgument(new Reference('router.route_provider'))
+        ->addTag('route_processor_outbound');
+    }
   }
 
 }
diff --git a/core/modules/rest/src/RouteProcessor/RestResourceGetRouteProcessorBC.php b/core/modules/rest/src/RouteProcessor/RestResourceGetRouteProcessorBC.php
new file mode 100644
index 0000000000..b1835d55cd
--- /dev/null
+++ b/core/modules/rest/src/RouteProcessor/RestResourceGetRouteProcessorBC.php
@@ -0,0 +1,80 @@
+<?php
+
+namespace Drupal\rest\RouteProcessor;
+
+use Drupal\Component\Utility\Crypt;
+use Drupal\Core\Render\BubbleableMetadata;
+use Drupal\Core\RouteProcessor\OutboundRouteProcessorInterface;
+use Drupal\Core\Routing\RouteProviderInterface;
+use Symfony\Component\Routing\Route;
+
+/**
+ * Processes the BC REST routes, to ensure old route names continue to work.
+ */
+class RestResourceGetRouteProcessorBC implements OutboundRouteProcessorInterface {
+
+  /**
+   * The available serialization formats.
+   *
+   * @var string[]
+   */
+  protected $serializerFormats = [];
+
+  /**
+   * The route provider.
+   *
+   * @var \Drupal\Core\Routing\RouteProviderInterface
+   */
+  protected $routeProvider;
+
+  /**
+   * Constructs a RestResourceGetRouteProcessorBC object.
+   *
+   * @param string[] $serializer_formats
+   *   The available serialization formats.
+   * @param \Drupal\Core\Routing\RouteProviderInterface $route_provider
+   *   The route provider.
+   */
+  public function __construct(array $serializer_formats, RouteProviderInterface $route_provider) {
+    $this->serializerFormats = $serializer_formats;
+    $this->routeProvider = $route_provider;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function processOutbound($route_name, Route $route, array &$parameters, BubbleableMetadata $bubbleable_metadata = NULL) {
+    $route_name_parts = explode('.', $route_name);
+    // BC: the REST module originally created per-format GET routes, instead
+    // of a single route. To minimize the surface of this BC layer, this uses
+    // route definitions that are as empty as possible, plus an outbound route
+    // processor.
+    // @see \Drupal\rest\Plugin\ResourceBase::routes()
+    if ($route_name_parts[0] === 'rest' && $route_name_parts[count($route_name_parts) - 2] === 'GET' && in_array($route_name_parts[count($route_name_parts) - 1], $this->serializerFormats, TRUE)) {
+      array_pop($route_name_parts);
+      $redirected_route_name = implode('.', $route_name_parts);
+      static::overwriteRoute($route, $this->routeProvider->getRouteByName($redirected_route_name));
+    }
+  }
+
+  /**
+   * Overwrites one route's metadata with the other's.
+   *
+   * @param \Symfony\Component\Routing\Route $target_route
+   *   The route whose metadata to overwrite.
+   * @param \Symfony\Component\Routing\Route $source_route
+   *   The route whose metadata to read from.
+   *
+   * @see \Symfony\Component\Routing\Route
+   */
+  protected static function overwriteRoute(Route $target_route, Route $source_route) {
+    $target_route->setPath($source_route->getPath());
+    $target_route->setDefaults($source_route->getDefaults());
+    $target_route->setRequirements($source_route->getRequirements());
+    $target_route->setOptions($source_route->getOptions());
+    $target_route->setHost($source_route->getHost());
+    $target_route->setSchemes($source_route->getSchemes());
+    $target_route->setMethods($source_route->getMethods());
+  }
+
+}
diff --git a/core/modules/rest/src/Routing/ResourceRoutes.php b/core/modules/rest/src/Routing/ResourceRoutes.php
index 5ba4c5da62..e9d54372e8 100644
--- a/core/modules/rest/src/Routing/ResourceRoutes.php
+++ b/core/modules/rest/src/Routing/ResourceRoutes.php
@@ -92,8 +92,10 @@ protected function getRoutesForResourceConfig(RestResourceConfigInterface $rest_
       /** @var \Symfony\Component\Routing\Route $route */
       // @todo: Are multiple methods possible here?
       $methods = $route->getMethods();
-      // Only expose routes where the method is enabled in the configuration.
-      if ($methods && ($method = $methods[0]) && $supported_formats = $rest_resource_config->getFormats($method)) {
+      // Only expose routes
+      // - that have an explicit method and allow >=1 format for that method
+      // - that exist for BC
+      if (($methods && ($method = $methods[0]) && $supported_formats = $rest_resource_config->getFormats($method)) || $route->hasOption('bc_route')) {
         $route->setRequirement('_csrf_request_header_token', 'TRUE');
 
         // Check that authentication providers are defined.
@@ -108,20 +110,16 @@ protected function getRoutesForResourceConfig(RestResourceConfigInterface $rest_
           continue;
         }
 
-        // If the route has a format requirement, then verify that the
-        // resource has it.
-        $format_requirement = $route->getRequirement('_format');
-        if ($format_requirement && !in_array($format_requirement, $rest_resource_config->getFormats($method))) {
-          continue;
-        }
-
         // The configuration has been validated, so we update the route to:
+        // - set the allowed response body content types/formats for methods
+        //   that may send response bodies
         // - set the allowed request body content types/formats for methods that
         //   allow request bodies to be sent
         // - set the allowed authentication providers
+        if (in_array($method, ['GET', 'HEAD', 'POST', 'PUT', 'PATCH'], TRUE)) {
+          $route->addRequirements(['_format' => implode('|', $rest_resource_config->getFormats($method))]);
+        }
         if (in_array($method, ['POST', 'PATCH', 'PUT'], TRUE)) {
-          // Restrict the incoming HTTP Content-type header to the allowed
-          // formats.
           $route->addRequirements(['_content_type_format' => implode('|', $rest_resource_config->getFormats($method))]);
         }
         $route->setOption('_auth', $rest_resource_config->getAuthenticationProviders($method));
diff --git a/core/modules/rest/tests/fixtures/update/drupal-8.rest-rest_post_update_resource_granularity.php b/core/modules/rest/tests/fixtures/update/drupal-8.rest-rest_post_update_resource_granularity.php
index aa94c63e55..989f579272 100644
Binary files a/core/modules/rest/tests/fixtures/update/drupal-8.rest-rest_post_update_resource_granularity.php and b/core/modules/rest/tests/fixtures/update/drupal-8.rest-rest_post_update_resource_granularity.php differ
diff --git a/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php b/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php
index 41d9eec849..47e0835a52 100644
--- a/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php
+++ b/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php
@@ -15,6 +15,7 @@
 use Drupal\Tests\rest\Functional\ResourceTestBase;
 use GuzzleHttp\RequestOptions;
 use Psr\Http\Message\ResponseInterface;
+use Symfony\Component\Routing\Exception\RouteNotFoundException;
 
 /**
  * Even though there is the generic EntityResource, it's necessary for every
@@ -633,7 +634,7 @@ public function testGet() {
     $this->assertSame(['text/plain; charset=UTF-8'], $response->getHeader('Content-Type'));
 
 
-    $url = Url::fromRoute('rest.entity.' . static::$entityTypeId . '.GET.' . static::$format);
+    $url = Url::fromRoute('rest.entity.' . static::$entityTypeId . '.GET');
     $url->setRouteParameter(static::$entityTypeId, 987654321);
     $url->setOption('query', ['_format' => static::$format]);
 
@@ -641,8 +642,28 @@ public function testGet() {
     // DX: 404 when GETting non-existing entity.
     $response = $this->request('GET', $url, $request_options);
     $path = str_replace('987654321', '{' . static::$entityTypeId . '}', $url->setAbsolute()->setOptions(['base_url' => '', 'query' => []])->toString());
-    $message = 'The "' . static::$entityTypeId . '" parameter was not converted for the path "' . $path . '" (route name: "rest.entity.' . static::$entityTypeId . '.GET.' . static::$format . '")';
+    $message = 'The "' . static::$entityTypeId . '" parameter was not converted for the path "' . $path . '" (route name: "rest.entity.' . static::$entityTypeId . '.GET")';
     $this->assertResourceErrorResponse(404, $message, $response);
+
+
+    // BC: rest_update_8501().
+    // Format-specific GET routes are deprecated. On new sites they no longer
+    // exist. On existing sites, they continue to be available, to ensure code
+    // creating links to them continues to work.
+    $bc_route = Url::fromRoute('rest.entity.' . static::$entityTypeId . '.GET.' . static::$format, $url->getRouteParameters(), $url->getOptions());
+    try {
+      $bc_route->toString(TRUE);
+      $this->assertTrue(FALSE);
+    }
+    catch (RouteNotFoundException $e) {
+      $this->assertTrue(TRUE);
+    }
+    // Enable BC layer.
+    $this->config('rest.settings')->set('bc.format_specific_get_routes', TRUE)->save(TRUE);
+    $this->rebuildContainer();
+    $this->resetAll();
+    $bc_route->setUrlGenerator($this->container->get('url_generator'));
+    $this->assertSame($url->toString(TRUE)->getGeneratedUrl(), $bc_route->toString(TRUE)->getGeneratedUrl());
   }
 
   /**
@@ -913,6 +934,7 @@ public function testPost() {
     if ($this->entity->getEntityType()->hasLinkTemplate('create')) {
       $this->entityStorage->load(static::$secondCreatedEntityId)->delete();
       $old_url = Url::fromUri('base:entity/' . static::$entityTypeId);
+      $old_url->setOption('query', ['_format' => static::$format]);
       $response = $this->request('POST', $old_url, $request_options);
       $this->assertResourceResponse(201, FALSE, $response);
     }
diff --git a/core/modules/user/src/Plugin/rest/resource/UserRegistrationResource.php b/core/modules/user/src/Plugin/rest/resource/UserRegistrationResource.php
index 6a243c3a1d..8c82a877b2 100644
--- a/core/modules/user/src/Plugin/rest/resource/UserRegistrationResource.php
+++ b/core/modules/user/src/Plugin/rest/resource/UserRegistrationResource.php
@@ -2,6 +2,7 @@
 
 namespace Drupal\user\Plugin\rest\resource;
 
+use Drupal\Core\Config\ConfigFactoryInterface;
 use Drupal\Core\Config\ImmutableConfig;
 use Drupal\Core\Session\AccountInterface;
 use Drupal\rest\ModifiedResourceResponse;
@@ -59,13 +60,15 @@ class UserRegistrationResource extends ResourceBase {
    *   The available serialization formats.
    * @param \Psr\Log\LoggerInterface $logger
    *   A logger instance.
+   * @param \Drupal\Core\Config\ImmutableConfig $rest_settings
+   *   A REST settings config instance.
    * @param \Drupal\Core\Config\ImmutableConfig $user_settings
    *   A user settings config instance.
    * @param \Drupal\Core\Session\AccountInterface $current_user
    *   The current user.
    */
-  public function __construct(array $configuration, $plugin_id, $plugin_definition, array $serializer_formats, LoggerInterface $logger, ImmutableConfig $user_settings, AccountInterface $current_user) {
-    parent::__construct($configuration, $plugin_id, $plugin_definition, $serializer_formats, $logger);
+  public function __construct(array $configuration, $plugin_id, $plugin_definition, array $serializer_formats, LoggerInterface $logger, ImmutableConfig $rest_settings, ImmutableConfig $user_settings, AccountInterface $current_user) {
+    parent::__construct($configuration, $plugin_id, $plugin_definition, $serializer_formats, $logger, $rest_settings);
     $this->userSettings = $user_settings;
     $this->currentUser = $current_user;
   }
@@ -80,6 +83,7 @@ public static function create(ContainerInterface $container, array $configuratio
       $plugin_definition,
       $container->getParameter('serializer.formats'),
       $container->get('logger.factory')->get('rest'),
+      $container->get('config.factory')->get('rest.settings'),
       $container->get('config.factory')->get('user.settings'),
       $container->get('current_user')
     );
diff --git a/core/modules/user/src/Tests/RestRegisterUserTest.php b/core/modules/user/src/Tests/RestRegisterUserTest.php
index 450c552919..31bcce4d29 100644
--- a/core/modules/user/src/Tests/RestRegisterUserTest.php
+++ b/core/modules/user/src/Tests/RestRegisterUserTest.php
@@ -2,6 +2,7 @@
 
 namespace Drupal\user\Tests;
 
+use Drupal\Core\Url;
 use Drupal\rest\Tests\RESTTestBase;
 use Drupal\user\Entity\Role;
 use Drupal\user\RoleInterface;
@@ -166,7 +167,7 @@ protected function registerUser($name, $include_password = TRUE) {
    */
   protected function registerRequest($name, $include_password = TRUE) {
     $serialized = $this->createSerializedUser($name, $include_password);
-    $this->httpRequest('/user/register', 'POST', $serialized, 'application/hal+json');
+    $this->httpRequest(Url::fromRoute('rest.user_registration.POST', ['_format' => 'hal_json']), 'POST', $serialized, 'application/hal+json');
   }
 
 }
diff --git a/core/modules/user/tests/src/Unit/UserRegistrationResourceTest.php b/core/modules/user/tests/src/Unit/UserRegistrationResourceTest.php
index 142685c22f..a66d77d7b2 100644
--- a/core/modules/user/tests/src/Unit/UserRegistrationResourceTest.php
+++ b/core/modules/user/tests/src/Unit/UserRegistrationResourceTest.php
@@ -58,6 +58,13 @@ class UserRegistrationResourceTest extends UnitTestCase {
   protected $reflection;
 
   /**
+   * A REST settings config instance.
+   *
+   * @var \Drupal\Core\Config\ImmutableConfig|\PHPUnit_Framework_MockObject_MockObject
+   */
+  protected $restSettings;
+
+  /**
    * A user settings config instance.
    *
    * @var \Drupal\Core\Config\ImmutableConfig|\PHPUnit_Framework_MockObject_MockObject
@@ -86,11 +93,12 @@ protected function setUp() {
 
     $this->logger = $this->prophesize(LoggerInterface::class)->reveal();
 
+    $this->restSettings = $this->prophesize(ImmutableConfig::class);
     $this->userSettings = $this->prophesize(ImmutableConfig::class);
 
     $this->currentUser = $this->prophesize(AccountInterface::class);
 
-    $this->testClass = new UserRegistrationResource([], 'plugin_id', '', [], $this->logger, $this->userSettings->reveal(), $this->currentUser->reveal());
+    $this->testClass = new UserRegistrationResource([], 'plugin_id', '', [], $this->logger, $this->restSettings->reveal(), $this->userSettings->reveal(), $this->currentUser->reveal());
     $this->reflection = new \ReflectionClass($this->testClass);
   }
 
@@ -122,7 +130,7 @@ public function testRegistrationAdminOnlyPost() {
 
     $this->currentUser->isAnonymous()->willReturn(TRUE);
 
-    $this->testClass = new UserRegistrationResource([], 'plugin_id', '', [], $this->logger, $this->userSettings->reveal(), $this->currentUser->reveal());
+    $this->testClass = new UserRegistrationResource([], 'plugin_id', '', [], $this->logger, $this->restSettings->reveal(), $this->userSettings->reveal(), $this->currentUser->reveal());
 
     $entity = $this->prophesize(User::class);
     $entity->isNew()->willReturn(TRUE);
@@ -138,7 +146,7 @@ public function testRegistrationAdminOnlyPost() {
   public function testRegistrationAnonymousOnlyPost() {
     $this->currentUser->isAnonymous()->willReturn(FALSE);
 
-    $this->testClass = new UserRegistrationResource([], 'plugin_id', '', [], $this->logger, $this->userSettings->reveal(), $this->currentUser->reveal());
+    $this->testClass = new UserRegistrationResource([], 'plugin_id', '', [], $this->logger, $this->restSettings->reveal(), $this->userSettings->reveal(), $this->currentUser->reveal());
 
     $entity = $this->prophesize(User::class);
     $entity->isNew()->willReturn(TRUE);
diff --git a/update.php b/update.php
index 59e808ed24..fc3d72bb1e 100644
--- a/update.php
+++ b/update.php
@@ -22,7 +22,7 @@
   gc_disable();
 }
 
-$kernel = new UpdateKernel('prod', $autoloader, FALSE);
+$kernel = new UpdateKernel('prod', $autoloader, TRUE);
 $request = Request::createFromGlobals();
 
 $response = $kernel->handle($request);
