diff --git a/core/core.services.yml b/core/core.services.yml
index 40c6a8a..453934b 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -1657,3 +1657,5 @@ services:
     class: Drupal\Core\EventSubscriber\RssResponseRelativeUrlFilter
     tags:
       - { name: event_subscriber }
+  shutdown_registry:
+      class: Drupal\Core\Utility\ShutDownRegistry
diff --git a/core/includes/batch.inc b/core/includes/batch.inc
index f84c01b..24049ad 100644
--- a/core/includes/batch.inc
+++ b/core/includes/batch.inc
@@ -48,7 +48,7 @@ function _batch_page(Request $request) {
   }
 
   // Register database update for the end of processing.
-  drupal_register_shutdown_function('_batch_shutdown');
+  \Drupal::service('shutdown_registry')->registerShutdownCallable('_batch_shutdown', TRUE);
 
   $build = array();
 
diff --git a/core/lib/Drupal/Core/Render/HtmlResponse.php b/core/lib/Drupal/Core/Render/HtmlResponse.php
index 555e504..1241cfa 100644
--- a/core/lib/Drupal/Core/Render/HtmlResponse.php
+++ b/core/lib/Drupal/Core/Render/HtmlResponse.php
@@ -5,7 +5,6 @@
 use Drupal\Core\Cache\CacheableMetadata;
 use Drupal\Core\Cache\CacheableResponseInterface;
 use Drupal\Core\Cache\CacheableResponseTrait;
-use Symfony\Component\HttpFoundation\Response;
 
 /**
  * A response that contains and can expose cacheability metadata and attachments.
diff --git a/core/lib/Drupal/Core/Render/Response.php b/core/lib/Drupal/Core/Render/Response.php
new file mode 100644
index 0000000..858c7f8
--- /dev/null
+++ b/core/lib/Drupal/Core/Render/Response.php
@@ -0,0 +1,31 @@
+<?php
+
+namespace Drupal\Core\Render;
+
+use Symfony\Component\HttpFoundation\Response as SymfonyResponse;
+
+/**
+ * Custom response class that uses the 'shutdown_registry' service.
+ *
+ * Determines whether fastcgi_finish_request should be called depending on
+ * shutdown_registry services.
+ */
+class Response extends SymfonyResponse {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function send() {
+    $this->sendHeaders();
+    $this->sendContent();
+
+    if (!\Drupal::service('shutdown_registry')->preventEarlyFlush() && function_exists('fastcgi_finish_request')) {
+      fastcgi_finish_request();
+    }
+    elseif ('cli' !== PHP_SAPI) {
+      static::closeOutputBuffers(0, TRUE);
+    }
+    return $this;
+  }
+
+}
diff --git a/core/lib/Drupal/Core/Utility/ShutDownRegistry.php b/core/lib/Drupal/Core/Utility/ShutDownRegistry.php
new file mode 100644
index 0000000..1a7fbda
--- /dev/null
+++ b/core/lib/Drupal/Core/Utility/ShutDownRegistry.php
@@ -0,0 +1,53 @@
+<?php
+
+namespace Drupal\Core\Utility;
+
+/**
+ * Registers showdown functions.
+ *
+ * @todo Replace all calls to drupal_register_shutdown_function() with calls to
+ * ::registerShutdownCallable().
+ * Deprecate drupal_register_shutdown_function() and move it's logic to
+ * :;registerShutdownCallable()
+ * Add ::getShutDownCallable() to replace &drupal_register_shutdown_function()
+ * calls.
+ *
+ * @todo \Drupal\Core\Render\HtmlResponse has been modified to extend this. Do
+ * other Responses need to be modified too.
+ */
+class ShutDownRegistry {
+
+  /**
+   * Whether to prevent fastcgi_finish_request from running.
+   *
+   * @var bool
+   */
+  protected $prevent_early_flush = FALSE;
+
+  /**
+   * Registers a shutdown callable.
+   *
+   * @param callable $callable
+   *   The callable.
+   * @param bool $prevent_early_flush
+   *   Whether early flushing should be prevented. One call with this TRUE will
+   *   prevent early flushing.
+   */
+  public function registerShutdownCallable(callable $callable, $prevent_early_flush = FALSE) {
+    drupal_register_shutdown_function($callable);
+    if ($prevent_early_flush) {
+      $this->prevent_early_flush = TRUE;
+    }
+  }
+
+  /**
+   * Gets whether early flushing of response should be prevented.
+   *
+   * @return bool
+   *   TRUE if early flushing should be prevented, FALSE otherwise.
+   */
+  public function preventEarlyFlush() {
+    return $this->prevent_early_flush;
+  }
+
+}
