diff --git a/core/lib/Drupal/Core/Form/FormCache.php b/core/lib/Drupal/Core/Form/FormCache.php
index 7064e10fb95dd551300e8185ca56232b9b4e5db5..9c931fdcae20723e37ab34034b6e19b8f27d1ada 100644
--- a/core/lib/Drupal/Core/Form/FormCache.php
+++ b/core/lib/Drupal/Core/Form/FormCache.php
@@ -8,6 +8,7 @@
 use Drupal\Core\KeyValueStore\KeyValueExpirableFactoryInterface;
 use Drupal\Core\PageCache\RequestPolicyInterface;
 use Drupal\Core\Session\AccountInterface;
+use Drupal\Core\Site\Settings;
 use Psr\Log\LoggerInterface;
 use Symfony\Component\HttpFoundation\RequestStack;
 
@@ -170,8 +171,8 @@ protected function loadCachedFormState($form_build_id, FormStateInterface $form_
    * {@inheritdoc}
    */
   public function setCache($form_build_id, $form, FormStateInterface $form_state) {
-    // 6 hours cache life time for forms should be plenty.
-    $expire = 21600;
+    // Cache forms for 6 hours by default.
+    $expire = Settings::get('form_cache_expiration', 21600);
 
     // Ensure that the form build_id embedded in the form structure is the same
     // as the one passed in as a parameter. This is an additional safety measure
diff --git a/core/tests/Drupal/KernelTests/Core/Form/FormCacheTest.php b/core/tests/Drupal/KernelTests/Core/Form/FormCacheTest.php
index 6425a3099d5c58db401320b595d094ca58020b30..f6fb4f8713a42a26d00c7ef522a36f11378ed6ae 100644
--- a/core/tests/Drupal/KernelTests/Core/Form/FormCacheTest.php
+++ b/core/tests/Drupal/KernelTests/Core/Form/FormCacheTest.php
@@ -5,6 +5,7 @@
 use Drupal\Core\Form\FormState;
 use Drupal\Core\Session\AnonymousUserSession;
 use Drupal\Core\Session\UserSession;
+use Drupal\Core\Site\Settings;
 use Drupal\KernelTests\KernelTestBase;
 
 /**
@@ -101,4 +102,16 @@ public function testNoCacheToken() {
     $account_switcher->switchBack();
   }
 
+  /**
+   * Tests the form cache with an overridden cache expiration.
+   */
+  public function testCacheCustomExpiration() {
+    // Override form cache expiration so that the cached form expired yesterday.
+    new Settings(['form_cache_expiration' => -1 * (24 * 60 * 60), 'hash_salt' => $this->randomMachineName()]);
+    \Drupal::formBuilder()->setCache($this->formBuildId, $this->form, $this->formState);
+
+    $cached_form_state = new FormState();
+    $this->assertFalse(\Drupal::formBuilder()->getCache($this->formBuildId, $cached_form_state), 'Expired form not returned from cache');
+  }
+
 }
diff --git a/sites/default/default.settings.php b/sites/default/default.settings.php
index 1720d11e43bfe77fa62f4234234a6d7e850d7322..c7dd194350e9f53b9849631b1b5e8042d1619665 100644
--- a/sites/default/default.settings.php
+++ b/sites/default/default.settings.php
@@ -440,6 +440,15 @@
  */
 # $settings['cache_ttl_4xx'] = 3600;
 
+/**
+ * Expiration of cached forms.
+ *
+ * Drupal's Form API stores details of forms in a cache and these entries are
+ * kept for at least 6 hours by default. Expired entries are cleared by cron.
+ *
+ * @see \Drupal\Core\Form\FormCache::setCache()
+ */
+# $settings['form_cache_expiration'] = 21600;
 
 /**
  * Class Loader.