diff --git a/core/lib/Drupal/Core/KeyValueStore/DatabaseStorage.php b/core/lib/Drupal/Core/KeyValueStore/DatabaseStorage.php
index 5e7d5c0a335c0b1de8668ddc124ef037d4ad95de..f678b415d1d85786d872a65d3c03824a656971c7 100644
--- a/core/lib/Drupal/Core/KeyValueStore/DatabaseStorage.php
+++ b/core/lib/Drupal/Core/KeyValueStore/DatabaseStorage.php
@@ -61,10 +61,16 @@ public function __construct($collection, SerializationInterface $serializer, Con
    * {@inheritdoc}
    */
   public function has($key) {
-    return (bool) $this->connection->query('SELECT 1 FROM {' . $this->connection->escapeTable($this->table) . '} WHERE [collection] = :collection AND [name] = :key', [
-      ':collection' => $this->collection,
-      ':key' => $key,
-    ])->fetchField();
+    try {
+      return (bool) $this->connection->query('SELECT 1 FROM {' . $this->connection->escapeTable($this->table) . '} WHERE [collection] = :collection AND [name] = :key', [
+        ':collection' => $this->collection,
+        ':key' => $key,
+      ])->fetchField();
+    }
+    catch (\Exception $e) {
+      $this->catchException($e);
+      return FALSE;
+    }
   }
 
   /**
@@ -92,9 +98,15 @@ public function getMultiple(array $keys) {
    * {@inheritdoc}
    */
   public function getAll() {
-    $result = $this->connection->query('SELECT [name], [value] FROM {' . $this->connection->escapeTable($this->table) . '} WHERE [collection] = :collection', [':collection' => $this->collection]);
-    $values = [];
+    try {
+      $result = $this->connection->query('SELECT [name], [value] FROM {' . $this->connection->escapeTable($this->table) . '} WHERE [collection] = :collection', [':collection' => $this->collection]);
+    }
+    catch (\Exception $e) {
+      $this->catchException($e);
+      $result = [];
+    }
 
+    $values = [];
     foreach ($result as $item) {
       if ($item) {
         $values[$item->name] = $this->serializer->decode($item->value);
@@ -104,9 +116,16 @@ public function getAll() {
   }
 
   /**
-   * {@inheritdoc}
+   * Saves a value for a given key.
+   *
+   * This will be called by set() within a try block.
+   *
+   * @param string $key
+   *   The key of the data to store.
+   * @param mixed $value
+   *   The data to store.
    */
-  public function set($key, $value) {
+  protected function doSet($key, $value) {
     $this->connection->merge($this->table)
       ->keys([
         'name' => $key,
@@ -119,7 +138,35 @@ public function set($key, $value) {
   /**
    * {@inheritdoc}
    */
-  public function setIfNotExists($key, $value) {
+  public function set($key, $value) {
+    try {
+      $this->doSet($key, $value);
+    }
+    catch (\Exception $e) {
+      // If there was an exception, try to create the table.
+      if ($this->ensureTableExists()) {
+        $this->doSet($key, $value);
+      }
+      else {
+        throw $e;
+      }
+    }
+  }
+
+  /**
+   * Saves a value for a given key if it does not exist yet.
+   *
+   * This will be called by setIfNotExists() within a try block.
+   *
+   * @param string $key
+   *   The key of the data to store.
+   * @param mixed $value
+   *   The data to store.
+   *
+   * @return bool
+   *   TRUE if the data was set, FALSE if it already existed.
+   */
+  public function doSetIfNotExists($key, $value) {
     $result = $this->connection->merge($this->table)
       ->insertFields([
         'collection' => $this->collection,
@@ -132,15 +179,38 @@ public function setIfNotExists($key, $value) {
     return $result == Merge::STATUS_INSERT;
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function setIfNotExists($key, $value) {
+    try {
+      return $this->doSetIfNotExists($key, $value);
+    }
+    catch (\Exception $e) {
+      // If there was an exception, try to create the table.
+      if ($this->ensureTableExists()) {
+        return $this->doSetIfNotExists($key, $value);
+      }
+      else {
+        throw $e;
+      }
+    }
+  }
+
   /**
    * {@inheritdoc}
    */
   public function rename($key, $new_key) {
-    $this->connection->update($this->table)
-      ->fields(['name' => $new_key])
-      ->condition('collection', $this->collection)
-      ->condition('name', $key)
-      ->execute();
+    try {
+      $this->connection->update($this->table)
+        ->fields(['name' => $new_key])
+        ->condition('collection', $this->collection)
+        ->condition('name', $key)
+        ->execute();
+    }
+    catch (\Exception $e) {
+      $this->catchException($e);
+    }
   }
 
   /**
@@ -149,20 +219,101 @@ public function rename($key, $new_key) {
   public function deleteMultiple(array $keys) {
     // Delete in chunks when a large array is passed.
     while ($keys) {
+      try {
+        $this->connection->delete($this->table)
+          ->condition('name', array_splice($keys, 0, 1000), 'IN')
+          ->condition('collection', $this->collection)
+          ->execute();
+      }
+      catch (\Exception $e) {
+        $this->catchException($e);
+      }
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function deleteAll() {
+    try {
       $this->connection->delete($this->table)
-        ->condition('name', array_splice($keys, 0, 1000), 'IN')
         ->condition('collection', $this->collection)
         ->execute();
     }
+    catch (\Exception $e) {
+      $this->catchException($e);
+    }
   }
 
   /**
-   * {@inheritdoc}
+   * Check if the table exists and create it if not.
+   *
+   * @return bool
+   *   TRUE if the table exists, FALSE if it does not exists.
    */
-  public function deleteAll() {
-    $this->connection->delete($this->table)
-      ->condition('collection', $this->collection)
-      ->execute();
+  protected function ensureTableExists() {
+    try {
+      $database_schema = $this->connection->schema();
+      if (!$database_schema->tableExists($this->table)) {
+        $database_schema->createTable($this->table, $this->schemaDefinition());
+        return TRUE;
+      }
+    }
+    // If the table already exists, then attempting to recreate it will throw an
+    // exception. In this case just catch the exception and do nothing.
+    catch (SchemaObjectExistsException $e) {
+      return TRUE;
+    }
+    return FALSE;
+  }
+
+  /**
+   * Act on an exception when the table might not have been created.
+   *
+   * If the table does not yet exist, that's fine, but if the table exists and
+   * yet the query failed, then the exception needs to propagate.
+   *
+   * @param \Exception $e
+   *   The exception.
+   *
+   * @throws \Exception
+   */
+  protected function catchException(\Exception $e) {
+    if ($this->connection->schema()->tableExists($this->table)) {
+      throw $e;
+    }
+  }
+
+  /**
+   * Defines the schema for the key_value table.
+  */
+  public static function schemaDefinition() {
+    return [
+      'description' => 'Generic key-value storage table. See the state system for an example.',
+      'fields' => [
+        'collection' => [
+          'description' => 'A named collection of key and value pairs.',
+          'type' => 'varchar_ascii',
+          'length' => 128,
+          'not null' => TRUE,
+          'default' => '',
+        ],
+        'name' => [
+          'description' => 'The key of the key-value pair. As KEY is a SQL reserved keyword, name was chosen instead.',
+          'type' => 'varchar_ascii',
+          'length' => 128,
+          'not null' => TRUE,
+          'default' => '',
+        ],
+        'value' => [
+          'description' => 'The value.',
+          'type' => 'blob',
+          'not null' => TRUE,
+          'size' => 'big',
+        ],
+      ],
+      'primary key' => ['collection', 'name'],
+    ];
   }
 
 }
diff --git a/core/lib/Drupal/Core/KeyValueStore/DatabaseStorageExpirable.php b/core/lib/Drupal/Core/KeyValueStore/DatabaseStorageExpirable.php
index 5dd4e716ab9a154d3ff0d8e94cbf2016e0b4fcf4..ffd4f1a69451c90d75e1cbefb54ab79d5f809b64 100644
--- a/core/lib/Drupal/Core/KeyValueStore/DatabaseStorageExpirable.php
+++ b/core/lib/Drupal/Core/KeyValueStore/DatabaseStorageExpirable.php
@@ -33,44 +33,75 @@ public function __construct($collection, SerializationInterface $serializer, Con
    * {@inheritdoc}
    */
   public function has($key) {
-    return (bool) $this->connection->query('SELECT 1 FROM {' . $this->connection->escapeTable($this->table) . '} WHERE [collection] = :collection AND [name] = :key AND [expire] > :now', [
-      ':collection' => $this->collection,
-      ':key' => $key,
-      ':now' => REQUEST_TIME,
-    ])->fetchField();
+    try {
+      return (bool) $this->connection->query('SELECT 1 FROM {' . $this->connection->escapeTable($this->table) . '} WHERE [collection] = :collection AND [name] = :key AND [expire] > :now', [
+        ':collection' => $this->collection,
+        ':key' => $key,
+        ':now' => REQUEST_TIME,
+      ])->fetchField();
+    }
+    catch (\Exception $e) {
+      $this->catchException($e);
+      return FALSE;
+    }
   }
 
   /**
    * {@inheritdoc}
    */
   public function getMultiple(array $keys) {
-    $values = $this->connection->query(
-      'SELECT [name], [value] FROM {' . $this->connection->escapeTable($this->table) . '} WHERE [expire] > :now AND [name] IN ( :keys[] ) AND [collection] = :collection',
-      [
-        ':now' => REQUEST_TIME,
-        ':keys[]' => $keys,
-        ':collection' => $this->collection,
-      ])->fetchAllKeyed();
-    return array_map([$this->serializer, 'decode'], $values);
+    try {
+      $values = $this->connection->query(
+        'SELECT [name], [value] FROM {' . $this->connection->escapeTable($this->table) . '} WHERE [expire] > :now AND [name] IN ( :keys[] ) AND [collection] = :collection',
+        [
+          ':now' => REQUEST_TIME,
+          ':keys[]' => $keys,
+          ':collection' => $this->collection,
+        ])->fetchAllKeyed();
+      return array_map([$this->serializer, 'decode'], $values);
+    }
+    catch (\Exception $e) {
+      // @todo: Perhaps if the database is never going to be available,
+      // key/value requests should return FALSE in order to allow exception
+      // handling to occur but for now, keep it an array, always.
+      // https://www.drupal.org/node/2787737
+      $this->catchException($e);
+    }
+    return [];
   }
 
   /**
    * {@inheritdoc}
    */
   public function getAll() {
-    $values = $this->connection->query(
-      'SELECT [name], [value] FROM {' . $this->connection->escapeTable($this->table) . '} WHERE [collection] = :collection AND [expire] > :now',
-      [
-        ':collection' => $this->collection,
-        ':now' => REQUEST_TIME,
-      ])->fetchAllKeyed();
-    return array_map([$this->serializer, 'decode'], $values);
+    try {
+      $values = $this->connection->query(
+        'SELECT [name], [value] FROM {' . $this->connection->escapeTable($this->table) . '} WHERE [collection] = :collection AND [expire] > :now',
+        [
+          ':collection' => $this->collection,
+          ':now' => REQUEST_TIME,
+        ])->fetchAllKeyed();
+      return array_map([$this->serializer, 'decode'], $values);
+    }
+    catch (\Exception $e) {
+      $this->catchException($e);
+    }
+    return [];
   }
 
   /**
-   * {@inheritdoc}
+   * Saves a value for a given key with a time to live.
+   *
+   * This will be called by setWithExpire() within a try block.
+   *
+   * @param string $key
+   *   The key of the data to store.
+   * @param mixed $value
+   *   The data to store.
+   * @param int $expire
+   *   The time to live for items, in seconds.
    */
-  public function setWithExpire($key, $value, $expire) {
+  protected function doSetWithExpire($key, $value, $expire) {
     $this->connection->merge($this->table)
       ->keys([
         'name' => $key,
@@ -86,7 +117,37 @@ public function setWithExpire($key, $value, $expire) {
   /**
    * {@inheritdoc}
    */
-  public function setWithExpireIfNotExists($key, $value, $expire) {
+  public function setWithExpire($key, $value, $expire) {
+    try {
+      $this->doSetWithExpire($key, $value, $expire);
+    }
+    catch (\Exception $e) {
+      // If there was an exception, then try to create the table.
+      if ($this->ensureTableExists()) {
+        $this->doSetWithExpire($key, $value, $expire);
+      }
+      else {
+        throw $e;
+      }
+    }
+  }
+
+  /**
+   * Sets a value for a given key with a time to live if it does not yet exist.
+   *
+   * This will be called by setWithExpireIfNotExists() within a try block.
+   *
+   * @param string $key
+   *   The key of the data to store.
+   * @param mixed $value
+   *   The data to store.
+   * @param int $expire
+   *   The time to live for items, in seconds.
+   *
+   * @return bool
+   *   TRUE if the data was set, or FALSE if it already existed.
+   */
+  protected function doSetWithExpireIfNotExists($key, $value, $expire) {
     if (!$this->has($key)) {
       $this->setWithExpire($key, $value, $expire);
       return TRUE;
@@ -94,6 +155,24 @@ public function setWithExpireIfNotExists($key, $value, $expire) {
     return FALSE;
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function setWithExpireIfNotExists($key, $value, $expire) {
+    try {
+      return $this->doSetWithExpireIfNotExists($key, $value, $expire);
+    }
+    catch (\Exception $e) {
+      // If there was an exception, try to create the table.
+      if ($this->ensureTableExists()) {
+        return $this->doSetWithExpireIfNotExists($key, $value, $expire);
+      }
+      else {
+        throw $e;
+      }
+    }
+  }
+
   /**
    * {@inheritdoc}
    */
@@ -110,4 +189,47 @@ public function deleteMultiple(array $keys) {
     parent::deleteMultiple($keys);
   }
 
+  /**
+   * Defines the schema for the key_value_expire table.
+   */
+  public static function schemaDefinition() {
+    return [
+      'description' => 'Generic key/value storage table with an expiration.',
+      'fields' => [
+        'collection' => [
+          'description' => 'A named collection of key and value pairs.',
+          'type' => 'varchar_ascii',
+          'length' => 128,
+          'not null' => TRUE,
+          'default' => '',
+        ],
+        'name' => [
+          // KEY is an SQL reserved word, so use 'name' as the key's field name.
+          'description' => 'The key of the key/value pair.',
+          'type' => 'varchar_ascii',
+          'length' => 128,
+          'not null' => TRUE,
+          'default' => '',
+        ],
+        'value' => [
+          'description' => 'The value of the key/value pair.',
+          'type' => 'blob',
+          'not null' => TRUE,
+          'size' => 'big',
+        ],
+        'expire' => [
+          'description' => 'The time since Unix epoch in seconds when this item expires. Defaults to the maximum possible time.',
+          'type' => 'int',
+          'not null' => TRUE,
+          'default' => 2147483647,
+        ],
+      ],
+      'primary key' => ['collection', 'name'],
+      'indexes' => [
+        'all' => ['name', 'collection', 'expire'],
+        'expire' => ['expire'],
+      ],
+    ];
+  }
+
 }
diff --git a/core/lib/Drupal/Core/KeyValueStore/KeyValueDatabaseExpirableFactory.php b/core/lib/Drupal/Core/KeyValueStore/KeyValueDatabaseExpirableFactory.php
index f9c9b4c17a6147023a6647f4da33c6b3c86a0e03..207a339fcb492330e7d731fd850d34d7cb3a4c5c 100644
--- a/core/lib/Drupal/Core/KeyValueStore/KeyValueDatabaseExpirableFactory.php
+++ b/core/lib/Drupal/Core/KeyValueStore/KeyValueDatabaseExpirableFactory.php
@@ -58,9 +58,31 @@ public function get($collection) {
    * Deletes expired items.
    */
   public function garbageCollection() {
-    $this->connection->delete('key_value_expire')
-      ->condition('expire', REQUEST_TIME, '<')
-      ->execute();
+    try {
+      $this->connection->delete('key_value_expire')
+        ->condition('expire', REQUEST_TIME, '<')
+        ->execute();
+    }
+    catch (\Exception $e) {
+      $this->catchException($e);
+    }
+  }
+
+  /**
+   * Act on an exception when the table might not have been created.
+   *
+   * If the table does not yet exist, that's fine, but if the table exists and
+   * yet the query failed, then the exception needs to propagate.
+   *
+   * @param \Exception $e
+   *   The exception.
+   *
+   * @throws \Exception
+   */
+  protected function catchException(\Exception $e) {
+    if ($this->connection->schema()->tableExists('key_value_expire')) {
+      throw $e;
+    }
   }
 
 }
diff --git a/core/lib/Drupal/Core/KeyValueStore/KeyValueStoreInterface.php b/core/lib/Drupal/Core/KeyValueStore/KeyValueStoreInterface.php
index d56004ee3b4e074bee134988f83d799d32fad3e9..8035a0ee4d85d96043af43859ee50c2b4e2683ea 100644
--- a/core/lib/Drupal/Core/KeyValueStore/KeyValueStoreInterface.php
+++ b/core/lib/Drupal/Core/KeyValueStore/KeyValueStoreInterface.php
@@ -48,7 +48,8 @@ public function get($key, $default = NULL);
    * @return array
    *   An associative array of items successfully returned, indexed by key.
    *
-   * @todo What's returned for non-existing keys?
+   * @todo Determine the best return value for non-existing keys in
+   *   https://www.drupal.org/node/2787737
    */
   public function getMultiple(array $keys);
 
diff --git a/core/modules/content_moderation/tests/src/Kernel/WorkspacesContentModerationStateTest.php b/core/modules/content_moderation/tests/src/Kernel/WorkspacesContentModerationStateTest.php
index 51b2e745c4a1c75d8a7d867e6bcb17ea14b3be95..17eba99f7c7d96d2b8bbf929a7d09271e8db48da 100644
--- a/core/modules/content_moderation/tests/src/Kernel/WorkspacesContentModerationStateTest.php
+++ b/core/modules/content_moderation/tests/src/Kernel/WorkspacesContentModerationStateTest.php
@@ -43,7 +43,7 @@ class WorkspacesContentModerationStateTest extends ContentModerationStateTest {
   protected function setUp(): void {
     parent::setUp();
 
-    $this->installSchema('system', ['key_value_expire', 'sequences']);
+    $this->installSchema('system', ['sequences']);
 
     $this->initializeWorkspacesModule();
     $this->switchToWorkspace('stage');
diff --git a/core/modules/datetime/tests/src/Kernel/DateTimeFormInjectionTest.php b/core/modules/datetime/tests/src/Kernel/DateTimeFormInjectionTest.php
index 7b9bc90d1436f3f57afe27898a5dc7e6572762b5..898127519db2ea442068deefed3aa53be8f0697a 100644
--- a/core/modules/datetime/tests/src/Kernel/DateTimeFormInjectionTest.php
+++ b/core/modules/datetime/tests/src/Kernel/DateTimeFormInjectionTest.php
@@ -37,7 +37,7 @@ class DateTimeFormInjectionTest extends KernelTestBase implements FormInterface
    */
   protected function setUp(): void {
     parent::setUp();
-    $this->installSchema('system', ['key_value_expire', 'sequences']);
+    $this->installSchema('system', ['sequences']);
   }
 
   /**
diff --git a/core/modules/datetime_range/tests/src/Kernel/SeparatorTranslationTest.php b/core/modules/datetime_range/tests/src/Kernel/SeparatorTranslationTest.php
index 0558f60af581b2ee07bba412b0d35bcedd5ad997..90989156279f4eeebeb4d28538e12f467d8046c1 100644
--- a/core/modules/datetime_range/tests/src/Kernel/SeparatorTranslationTest.php
+++ b/core/modules/datetime_range/tests/src/Kernel/SeparatorTranslationTest.php
@@ -54,7 +54,7 @@ protected function setUp(): void {
     $this->installEntitySchema('entity_test');
     $this->installEntitySchema('user');
     $this->installConfig(['system']);
-    $this->installSchema('system', ['sequences', 'key_value']);
+    $this->installSchema('system', ['sequences']);
 
     // Add a datetime range field.
     $this->fieldStorage = FieldStorageConfig::create([
diff --git a/core/modules/dblog/tests/src/Kernel/DbLogFormInjectionTest.php b/core/modules/dblog/tests/src/Kernel/DbLogFormInjectionTest.php
index 2b9a67a0fc051ddd99e2b983fd79e45634732a02..66f69641c75f368a7d7f753a1bd897f6a688ae44 100644
--- a/core/modules/dblog/tests/src/Kernel/DbLogFormInjectionTest.php
+++ b/core/modules/dblog/tests/src/Kernel/DbLogFormInjectionTest.php
@@ -78,7 +78,7 @@ public function submitForm(array &$form, FormStateInterface $form_state) {
   protected function setUp(): void {
     parent::setUp();
     $this->installSchema('dblog', ['watchdog']);
-    $this->installSchema('system', ['key_value_expire', 'sequences']);
+    $this->installSchema('system', ['sequences']);
     $this->installEntitySchema('user');
     $this->logger = \Drupal::logger('test_logger');
     $test_user = User::create([
diff --git a/core/modules/dblog/tests/src/Kernel/DbLogTest.php b/core/modules/dblog/tests/src/Kernel/DbLogTest.php
index 7900d624bb7c7bfed4bf6a5f23bab0f269f14407..ae16af492fe7b334670ce50d5832f1a72548336c 100644
--- a/core/modules/dblog/tests/src/Kernel/DbLogTest.php
+++ b/core/modules/dblog/tests/src/Kernel/DbLogTest.php
@@ -28,7 +28,7 @@ protected function setUp(): void {
     parent::setUp();
 
     $this->installSchema('dblog', ['watchdog']);
-    $this->installSchema('system', ['key_value_expire', 'sequences']);
+    $this->installSchema('system', ['sequences']);
     $this->installConfig(['system']);
   }
 
diff --git a/core/modules/editor/tests/src/Kernel/EditorImageDialogTest.php b/core/modules/editor/tests/src/Kernel/EditorImageDialogTest.php
index 197605c6ec29b09886a97071a18fbc5b6a69a024..9342193e92b556effe4d859aa120e2dd4de18dee 100644
--- a/core/modules/editor/tests/src/Kernel/EditorImageDialogTest.php
+++ b/core/modules/editor/tests/src/Kernel/EditorImageDialogTest.php
@@ -43,7 +43,6 @@ class EditorImageDialogTest extends EntityKernelTestBase {
   protected function setUp(): void {
     parent::setUp();
     $this->installEntitySchema('file');
-    $this->installSchema('system', ['key_value_expire']);
     $this->installSchema('node', ['node_access']);
     $this->installSchema('file', ['file_usage']);
     $this->installConfig(['node']);
diff --git a/core/modules/field/tests/src/Kernel/FieldKernelTestBase.php b/core/modules/field/tests/src/Kernel/FieldKernelTestBase.php
index bd810dc42dae10daa0f6742ab3ef222f4e5ef5b0..004979bd17e0a792234c4b0da1e0a53281108db3 100644
--- a/core/modules/field/tests/src/Kernel/FieldKernelTestBase.php
+++ b/core/modules/field/tests/src/Kernel/FieldKernelTestBase.php
@@ -54,7 +54,7 @@ protected function setUp() {
 
     $this->installEntitySchema('entity_test');
     $this->installEntitySchema('user');
-    $this->installSchema('system', ['sequences', 'key_value']);
+    $this->installSchema('system', ['sequences']);
 
     // Set default storage backend and configure the theme system.
     $this->installConfig(['field', 'system']);
diff --git a/core/modules/layout_builder/tests/src/Kernel/DefaultsSectionStorageTest.php b/core/modules/layout_builder/tests/src/Kernel/DefaultsSectionStorageTest.php
index 81f6f02b6ce35bd2deba8f39933e78cc52259190..bfa49065b569f0deca86764468e870bfcb15599e 100644
--- a/core/modules/layout_builder/tests/src/Kernel/DefaultsSectionStorageTest.php
+++ b/core/modules/layout_builder/tests/src/Kernel/DefaultsSectionStorageTest.php
@@ -48,7 +48,6 @@ protected function setUp(): void {
     parent::setUp();
 
     entity_test_create_bundle('bundle_with_extra_fields');
-    $this->installSchema('system', ['key_value_expire']);
     $this->installEntitySchema('entity_test');
     $this->installEntitySchema('user');
     $this->installConfig(['layout_builder_defaults_test']);
diff --git a/core/modules/layout_builder/tests/src/Kernel/LayoutBuilderCompatibilityTestBase.php b/core/modules/layout_builder/tests/src/Kernel/LayoutBuilderCompatibilityTestBase.php
index 0a6a7e48439f29037cfbb335391320ad033e9bf8..629f530cc08ab4c2ed85672ea62f7525624d8af2 100644
--- a/core/modules/layout_builder/tests/src/Kernel/LayoutBuilderCompatibilityTestBase.php
+++ b/core/modules/layout_builder/tests/src/Kernel/LayoutBuilderCompatibilityTestBase.php
@@ -42,7 +42,6 @@ protected function setUp() {
 
     $this->installEntitySchema('entity_test_base_field_display');
     $this->installConfig(['filter']);
-    $this->installSchema('system', ['key_value_expire']);
 
     // Set up a non-admin user that is allowed to view test entities.
     \Drupal::currentUser()->setAccount($this->createUser(['uid' => 2], ['view test entity']));
diff --git a/core/modules/layout_builder/tests/src/Kernel/LayoutEntityHelperTraitTest.php b/core/modules/layout_builder/tests/src/Kernel/LayoutEntityHelperTraitTest.php
index 16e84e5c5c6c051bded4f5c1ccf0a5990c81d436..c1d4c30a66a12d8bee1d75cad7de69f776f22bc8 100644
--- a/core/modules/layout_builder/tests/src/Kernel/LayoutEntityHelperTraitTest.php
+++ b/core/modules/layout_builder/tests/src/Kernel/LayoutEntityHelperTraitTest.php
@@ -41,7 +41,6 @@ class LayoutEntityHelperTraitTest extends KernelTestBase {
   protected function setUp(): void {
     parent::setUp();
 
-    $this->installSchema('system', ['key_value_expire']);
     $this->installEntitySchema('user');
     $this->installEntitySchema('entity_test');
   }
diff --git a/core/modules/layout_builder/tests/src/Kernel/OverridesSectionStorageTest.php b/core/modules/layout_builder/tests/src/Kernel/OverridesSectionStorageTest.php
index 822f121a7ebf259105671481095805da330d427f..ef67ae87ac009b6ac43a596b211f8238808ccb39 100644
--- a/core/modules/layout_builder/tests/src/Kernel/OverridesSectionStorageTest.php
+++ b/core/modules/layout_builder/tests/src/Kernel/OverridesSectionStorageTest.php
@@ -51,7 +51,6 @@ protected function setUp(): void {
     parent::setUp();
 
     $this->setUpCurrentUser();
-    $this->installSchema('system', ['key_value_expire']);
     $this->installEntitySchema('entity_test');
 
     $definition = $this->container->get('plugin.manager.layout_builder.section_storage')->getDefinition('overrides');
diff --git a/core/modules/layout_builder/tests/src/Kernel/SectionStorageTestBase.php b/core/modules/layout_builder/tests/src/Kernel/SectionStorageTestBase.php
index 567645ef768c653bf0fa522384a0e7449fe531e1..154e4e13a156da59fc5eb738896219e0025c58b1 100644
--- a/core/modules/layout_builder/tests/src/Kernel/SectionStorageTestBase.php
+++ b/core/modules/layout_builder/tests/src/Kernel/SectionStorageTestBase.php
@@ -33,8 +33,6 @@ abstract class SectionStorageTestBase extends EntityKernelTestBase {
   protected function setUp() {
     parent::setUp();
 
-    $this->installSchema('system', ['key_value_expire']);
-
     $section_data = [
       new Section('layout_test_plugin', [], [
         'first-uuid' => new SectionComponent('first-uuid', 'content', ['id' => 'foo']),
diff --git a/core/modules/layout_builder/tests/src/Kernel/TranslatableFieldTest.php b/core/modules/layout_builder/tests/src/Kernel/TranslatableFieldTest.php
index b7a1ee436bc62dc5e5695ec08884915cd2d91e34..68eb7cb61cc639093f24bebf6b25f08b633ff8ae 100644
--- a/core/modules/layout_builder/tests/src/Kernel/TranslatableFieldTest.php
+++ b/core/modules/layout_builder/tests/src/Kernel/TranslatableFieldTest.php
@@ -38,7 +38,6 @@ class TranslatableFieldTest extends KernelTestBase {
   protected function setUp(): void {
     parent::setUp();
 
-    $this->installSchema('system', ['key_value_expire']);
     $this->installEntitySchema('entity_test');
 
     // Create a translation.
diff --git a/core/modules/media_library/tests/src/Kernel/MediaLibraryAccessTest.php b/core/modules/media_library/tests/src/Kernel/MediaLibraryAccessTest.php
index 1685818b213d973003a28bb63579b1e223830d92..5101c3f6b97ac1d07098b595d3bdea00a5ad582f 100644
--- a/core/modules/media_library/tests/src/Kernel/MediaLibraryAccessTest.php
+++ b/core/modules/media_library/tests/src/Kernel/MediaLibraryAccessTest.php
@@ -49,7 +49,7 @@ protected function setUp(): void {
     $this->installEntitySchema('user');
     $this->installEntitySchema('file');
     $this->installSchema('file', 'file_usage');
-    $this->installSchema('system', ['sequences', 'key_value_expire']);
+    $this->installSchema('system', ['sequences']);
     $this->installEntitySchema('entity_test');
     $this->installEntitySchema('filter_format');
     $this->installEntitySchema('media');
diff --git a/core/modules/media_library/tests/src/Kernel/MediaLibraryAddFormTest.php b/core/modules/media_library/tests/src/Kernel/MediaLibraryAddFormTest.php
index 7c848ed42dd35470b5e941a884399751f8109529..8d8f3fc3276813fdefaf4f4d9c37d0f3a4932319 100644
--- a/core/modules/media_library/tests/src/Kernel/MediaLibraryAddFormTest.php
+++ b/core/modules/media_library/tests/src/Kernel/MediaLibraryAddFormTest.php
@@ -43,7 +43,7 @@ protected function setUp(): void {
     $this->installEntitySchema('user');
     $this->installEntitySchema('file');
     $this->installSchema('file', 'file_usage');
-    $this->installSchema('system', ['sequences', 'key_value_expire']);
+    $this->installSchema('system', ['sequences']);
     $this->installEntitySchema('media');
     $this->installConfig([
       'field',
diff --git a/core/modules/media_library/tests/src/Kernel/MediaLibraryWidgetTest.php b/core/modules/media_library/tests/src/Kernel/MediaLibraryWidgetTest.php
index 450bbda0dca4b578aa269bd3081a1e724b17a7a1..e5fc54ff9e20dd7ce838f38c54df75e96a819398 100644
--- a/core/modules/media_library/tests/src/Kernel/MediaLibraryWidgetTest.php
+++ b/core/modules/media_library/tests/src/Kernel/MediaLibraryWidgetTest.php
@@ -61,7 +61,7 @@ protected function setUp(): void {
     $this->installEntitySchema('entity_test');
     $this->installEntitySchema('entity_test_rev');
     $this->installEntitySchema('user');
-    $this->installSchema('system', ['sequences', 'key_value_expire']);
+    $this->installSchema('system', ['sequences']);
     $this->installConfig([
       'system',
       'image',
diff --git a/core/modules/node/tests/src/Kernel/Migrate/d6/NodeTranslationRedirectTest.php b/core/modules/node/tests/src/Kernel/Migrate/d6/NodeTranslationRedirectTest.php
index 5baeff7a249bd8e7922b0250b863bd8e4aac08b5..eec4ca71204532c920997fba7d5b75d18e9530be 100644
--- a/core/modules/node/tests/src/Kernel/Migrate/d6/NodeTranslationRedirectTest.php
+++ b/core/modules/node/tests/src/Kernel/Migrate/d6/NodeTranslationRedirectTest.php
@@ -36,7 +36,6 @@ protected function setUp(): void {
     $this->installEntitySchema('node');
     $this->installConfig(['node']);
     $this->installSchema('node', ['node_access']);
-    $this->installSchema('system', ['key_value']);
     $this->migrateUsers(FALSE);
     $this->migrateFields();
 
diff --git a/core/modules/node/tests/src/Kernel/Migrate/d7/NodeTranslationRedirectTest.php b/core/modules/node/tests/src/Kernel/Migrate/d7/NodeTranslationRedirectTest.php
index 614ee6bbbd8634243c35a8ba21d9846f17e8f48d..d8926d1a9ac31bcac336268675481eb6fe3b27cc 100644
--- a/core/modules/node/tests/src/Kernel/Migrate/d7/NodeTranslationRedirectTest.php
+++ b/core/modules/node/tests/src/Kernel/Migrate/d7/NodeTranslationRedirectTest.php
@@ -37,7 +37,6 @@ protected function setUp(): void {
     $this->setUpCurrentUser();
 
     $this->installSchema('node', ['node_access']);
-    $this->installSchema('system', ['key_value']);
 
     $this->migrateUsers(FALSE);
     $this->migrateContentTypes();
diff --git a/core/modules/system/system.install b/core/modules/system/system.install
index 66ac09793a755a9409d7006e3caa51910ec2939f..4b713531a96d0474ac254c15460e55e605eb8324 100644
--- a/core/modules/system/system.install
+++ b/core/modules/system/system.install
@@ -1330,71 +1330,6 @@ function system_install() {
  * Implements hook_schema().
  */
 function system_schema() {
-  $schema['key_value'] = [
-    'description' => 'Generic key-value storage table. See the state system for an example.',
-    'fields' => [
-      'collection' => [
-        'description' => 'A named collection of key and value pairs.',
-        'type' => 'varchar_ascii',
-        'length' => 128,
-        'not null' => TRUE,
-        'default' => '',
-      ],
-      'name' => [
-        'description' => 'The key of the key-value pair. As KEY is a SQL reserved keyword, name was chosen instead.',
-        'type' => 'varchar_ascii',
-        'length' => 128,
-        'not null' => TRUE,
-        'default' => '',
-      ],
-      'value' => [
-        'description' => 'The value.',
-        'type' => 'blob',
-        'not null' => TRUE,
-        'size' => 'big',
-      ],
-    ],
-    'primary key' => ['collection', 'name'],
-  ];
-
-  $schema['key_value_expire'] = [
-    'description' => 'Generic key/value storage table with an expiration.',
-    'fields' => [
-      'collection' => [
-        'description' => 'A named collection of key and value pairs.',
-        'type' => 'varchar_ascii',
-        'length' => 128,
-        'not null' => TRUE,
-        'default' => '',
-      ],
-      'name' => [
-        // KEY is an SQL reserved word, so use 'name' as the key's field name.
-        'description' => 'The key of the key/value pair.',
-        'type' => 'varchar_ascii',
-        'length' => 128,
-        'not null' => TRUE,
-        'default' => '',
-      ],
-      'value' => [
-        'description' => 'The value of the key/value pair.',
-        'type' => 'blob',
-        'not null' => TRUE,
-        'size' => 'big',
-      ],
-      'expire' => [
-        'description' => 'The time since Unix epoch in seconds when this item expires. Defaults to the maximum possible time.',
-        'type' => 'int',
-        'not null' => TRUE,
-        'default' => 2147483647,
-      ],
-    ],
-    'primary key' => ['collection', 'name'],
-    'indexes' => [
-      'all' => ['name', 'collection', 'expire'],
-      'expire' => ['expire'],
-    ],
-  ];
-
   $schema['sequences'] = [
     'description' => 'Stores IDs.',
     'fields' => [
diff --git a/core/modules/system/tests/src/Kernel/System/CronQueueTest.php b/core/modules/system/tests/src/Kernel/System/CronQueueTest.php
index 7623fd92bdf9c6b7875c404c980697d9a598184e..0a0475f1bbc5f9cefe0c68d24273980b81bed250 100644
--- a/core/modules/system/tests/src/Kernel/System/CronQueueTest.php
+++ b/core/modules/system/tests/src/Kernel/System/CronQueueTest.php
@@ -39,10 +39,6 @@ class CronQueueTest extends KernelTestBase {
   protected function setUp(): void {
     parent::setUp();
 
-    // These additional tables are necessary because $this->cron->run() calls
-    // system_cron().
-    $this->installSchema('system', ['key_value_expire']);
-
     $this->connection = Database::getConnection();
     $this->cron = \Drupal::service('cron');
   }
diff --git a/core/modules/views/tests/src/Kernel/ViewsKernelTestBase.php b/core/modules/views/tests/src/Kernel/ViewsKernelTestBase.php
index 84b560cffd6cf7c5ac2af6b99b90ab8417f7d7cc..429614b18a915445cac0d70fbef48aa6f628e64e 100644
--- a/core/modules/views/tests/src/Kernel/ViewsKernelTestBase.php
+++ b/core/modules/views/tests/src/Kernel/ViewsKernelTestBase.php
@@ -48,7 +48,7 @@ abstract class ViewsKernelTestBase extends KernelTestBase {
   protected function setUp($import_test_views = TRUE) {
     parent::setUp();
 
-    $this->installSchema('system', ['sequences', 'key_value_expire']);
+    $this->installSchema('system', ['sequences']);
     $this->setUpFixtures();
 
     if ($import_test_views) {
diff --git a/core/modules/workspaces/tests/src/Kernel/WorkspaceCRUDTest.php b/core/modules/workspaces/tests/src/Kernel/WorkspaceCRUDTest.php
index 75bfdc013556a9d5ebc45ada20d5313432b0401b..19dc0e166167242a29d5d3862a69c2f518dad111 100644
--- a/core/modules/workspaces/tests/src/Kernel/WorkspaceCRUDTest.php
+++ b/core/modules/workspaces/tests/src/Kernel/WorkspaceCRUDTest.php
@@ -64,7 +64,6 @@ protected function setUp(): void {
 
     $this->setUpCurrentUser();
 
-    $this->installSchema('system', ['key_value_expire']);
     $this->installSchema('node', ['node_access']);
 
     $this->installEntitySchema('workspace');
diff --git a/core/modules/workspaces/tests/src/Kernel/WorkspaceIntegrationTest.php b/core/modules/workspaces/tests/src/Kernel/WorkspaceIntegrationTest.php
index 06fe8a906978869362f2241560588bbeeb2d8f21..fc647174aa1df6ada1c9c7317476e4aca9d6214b 100644
--- a/core/modules/workspaces/tests/src/Kernel/WorkspaceIntegrationTest.php
+++ b/core/modules/workspaces/tests/src/Kernel/WorkspaceIntegrationTest.php
@@ -86,7 +86,7 @@ protected function setUp(): void {
 
     $this->installConfig(['filter', 'node', 'system', 'language', 'content_translation']);
 
-    $this->installSchema('system', ['key_value_expire', 'sequences']);
+    $this->installSchema('system', ['sequences']);
     $this->installSchema('node', ['node_access']);
 
     $language = ConfigurableLanguage::createFromLangcode('de');
diff --git a/core/modules/workspaces/tests/src/Kernel/WorkspaceMergerTest.php b/core/modules/workspaces/tests/src/Kernel/WorkspaceMergerTest.php
index fad38814481262ab2aef4e69c1ce928312049bb6..d8aff40638267ef3c06b16430096db3300afcd53 100644
--- a/core/modules/workspaces/tests/src/Kernel/WorkspaceMergerTest.php
+++ b/core/modules/workspaces/tests/src/Kernel/WorkspaceMergerTest.php
@@ -61,7 +61,7 @@ protected function setUp(): void {
 
     $this->installConfig(['filter', 'node', 'system']);
 
-    $this->installSchema('system', ['key_value_expire', 'sequences']);
+    $this->installSchema('system', ['sequences']);
     $this->installSchema('node', ['node_access']);
 
     $this->createContentType(['type' => 'article']);
diff --git a/core/tests/Drupal/KernelTests/Core/Action/DeleteActionTest.php b/core/tests/Drupal/KernelTests/Core/Action/DeleteActionTest.php
index 9d3bd1ac994aeab75caae0693acc5e9a8be4c969..186cb468af6dcbb4f9112b4ad4f04c047610676b 100644
--- a/core/tests/Drupal/KernelTests/Core/Action/DeleteActionTest.php
+++ b/core/tests/Drupal/KernelTests/Core/Action/DeleteActionTest.php
@@ -27,7 +27,7 @@ protected function setUp(): void {
     parent::setUp();
     $this->installEntitySchema('entity_test_mulrevpub');
     $this->installEntitySchema('user');
-    $this->installSchema('system', ['sequences', 'key_value_expire']);
+    $this->installSchema('system', ['sequences']);
 
     $this->testUser = User::create([
       'name' => 'foobar',
diff --git a/core/tests/Drupal/KernelTests/Core/Command/DbDumpTest.php b/core/tests/Drupal/KernelTests/Core/Command/DbDumpTest.php
index 3e16fff33316c3db69585f6720e93d740bb7d577..d121b8c3c8319a667f42aad52c902b5a5754e5bb 100644
--- a/core/tests/Drupal/KernelTests/Core/Command/DbDumpTest.php
+++ b/core/tests/Drupal/KernelTests/Core/Command/DbDumpTest.php
@@ -89,10 +89,7 @@ protected function setUp(): void {
     }
 
     // Create some schemas so our export contains tables.
-    $this->installSchema('system', [
-      'key_value_expire',
-      'sessions',
-    ]);
+    $this->installSchema('system', ['sessions']);
     $this->installSchema('dblog', ['watchdog']);
     $this->installEntitySchema('block_content');
     $this->installEntitySchema('user');
@@ -134,7 +131,6 @@ protected function setUp(): void {
       'cache_discovery',
       'cache_entity',
       'file_managed',
-      'key_value_expire',
       'menu_link_content',
       'menu_link_content_data',
       'menu_link_content_revision',
diff --git a/core/tests/Drupal/KernelTests/Core/Element/PathElementFormTest.php b/core/tests/Drupal/KernelTests/Core/Element/PathElementFormTest.php
index ae19939932eb7827004cf0ba1ef40cb0ae676f43..668fabda1bc29d14706f8df7bb06202edf69f6fc 100644
--- a/core/tests/Drupal/KernelTests/Core/Element/PathElementFormTest.php
+++ b/core/tests/Drupal/KernelTests/Core/Element/PathElementFormTest.php
@@ -37,7 +37,7 @@ class PathElementFormTest extends KernelTestBase implements FormInterface {
    */
   protected function setUp(): void {
     parent::setUp();
-    $this->installSchema('system', ['sequences', 'key_value_expire']);
+    $this->installSchema('system', ['sequences']);
     $this->installEntitySchema('user');
     /** @var \Drupal\user\RoleInterface $role */
     $role = Role::create([
diff --git a/core/tests/Drupal/KernelTests/Core/Entity/Element/EntityAutocompleteElementFormTest.php b/core/tests/Drupal/KernelTests/Core/Entity/Element/EntityAutocompleteElementFormTest.php
index b305c585010e66d1810f779f75af06e2f83e061c..1639a301b52a0b7e2519b175f8329f11f3888952 100644
--- a/core/tests/Drupal/KernelTests/Core/Entity/Element/EntityAutocompleteElementFormTest.php
+++ b/core/tests/Drupal/KernelTests/Core/Entity/Element/EntityAutocompleteElementFormTest.php
@@ -46,7 +46,6 @@ class EntityAutocompleteElementFormTest extends EntityKernelTestBase implements
   protected function setUp(): void {
     parent::setUp();
 
-    $this->installSchema('system', ['key_value_expire']);
     $this->installEntitySchema('entity_test_string_id');
 
     $this->testUser = User::create([
diff --git a/core/tests/Drupal/KernelTests/Core/Entity/EntityAutocompleteTest.php b/core/tests/Drupal/KernelTests/Core/Entity/EntityAutocompleteTest.php
index b8b9d670a7e1f9b8d56c2d53ed3b3a15dfd1de82..728b9ea2515b00bcf5917568e0872b1eefaa913a 100644
--- a/core/tests/Drupal/KernelTests/Core/Entity/EntityAutocompleteTest.php
+++ b/core/tests/Drupal/KernelTests/Core/Entity/EntityAutocompleteTest.php
@@ -32,14 +32,6 @@ class EntityAutocompleteTest extends EntityKernelTestBase {
    */
   protected $bundle = 'entity_test';
 
-  /**
-   * {@inheritdoc}
-   */
-  protected function setUp(): void {
-    parent::setUp();
-    $this->installSchema('system', ['key_value']);
-  }
-
   /**
    * Tests autocompletion edge cases with slashes in the names.
    */
diff --git a/core/tests/Drupal/KernelTests/Core/Entity/FieldWidgetConstraintValidatorTest.php b/core/tests/Drupal/KernelTests/Core/Entity/FieldWidgetConstraintValidatorTest.php
index 2a35cce1851006bf78d485f238ff2bac540ba67f..4d590d1c7302a019edef7f22c5d8d43e5d313815 100644
--- a/core/tests/Drupal/KernelTests/Core/Entity/FieldWidgetConstraintValidatorTest.php
+++ b/core/tests/Drupal/KernelTests/Core/Entity/FieldWidgetConstraintValidatorTest.php
@@ -29,8 +29,6 @@ class FieldWidgetConstraintValidatorTest extends KernelTestBase {
   protected function setUp(): void {
     parent::setUp();
 
-    $this->installSchema('system', ['key_value']);
-
     $this->installEntitySchema('user');
     $this->installEntitySchema('entity_test_composite_constraint');
   }
diff --git a/core/tests/Drupal/KernelTests/Core/File/DirectoryTest.php b/core/tests/Drupal/KernelTests/Core/File/DirectoryTest.php
index 4338fe78aa07ac19e47b7feeac3f73740d0251c0..020d6134e4d9543cd07681651abda312d4d419a8 100644
--- a/core/tests/Drupal/KernelTests/Core/File/DirectoryTest.php
+++ b/core/tests/Drupal/KernelTests/Core/File/DirectoryTest.php
@@ -15,20 +15,6 @@
  */
 class DirectoryTest extends FileTestBase {
 
-  /**
-   * Modules to enable.
-   *
-   * @var array
-   */
-  protected static $modules = ['system'];
-
-  protected function setUp(): void {
-    parent::setUp();
-
-    // These additional tables are necessary due to the call to system_cron().
-    $this->installSchema('system', ['key_value_expire']);
-  }
-
   /**
    * Test local directory handling functions.
    */
diff --git a/core/tests/Drupal/KernelTests/Core/Form/ExternalFormUrlTest.php b/core/tests/Drupal/KernelTests/Core/Form/ExternalFormUrlTest.php
index 9c7aae1d808f1a93ffe0c64f78cf3c9f21a80fcc..de8865a42ebdaa3435908975f8d5ab9ef091e221 100644
--- a/core/tests/Drupal/KernelTests/Core/Form/ExternalFormUrlTest.php
+++ b/core/tests/Drupal/KernelTests/Core/Form/ExternalFormUrlTest.php
@@ -53,7 +53,7 @@ public function submitForm(array &$form, FormStateInterface $form_state) {}
    */
   protected function setUp(): void {
     parent::setUp();
-    $this->installSchema('system', ['key_value_expire', 'sequences']);
+    $this->installSchema('system', ['sequences']);
     $this->installEntitySchema('user');
 
     $test_user = User::create([
diff --git a/core/tests/Drupal/KernelTests/Core/Form/FormCacheTest.php b/core/tests/Drupal/KernelTests/Core/Form/FormCacheTest.php
index c80cd979ba1391e6acb7c19b89aa54ac25736585..4955fb8c3699e3c0a1ee931c8b58b5dfbb2eea84 100644
--- a/core/tests/Drupal/KernelTests/Core/Form/FormCacheTest.php
+++ b/core/tests/Drupal/KernelTests/Core/Form/FormCacheTest.php
@@ -40,7 +40,6 @@ class FormCacheTest extends KernelTestBase {
 
   protected function setUp(): void {
     parent::setUp();
-    $this->installSchema('system', ['key_value_expire']);
 
     $this->formBuildId = $this->randomMachineName();
     $this->form = [
diff --git a/core/tests/Drupal/KernelTests/Core/Form/FormDefaultHandlersTest.php b/core/tests/Drupal/KernelTests/Core/Form/FormDefaultHandlersTest.php
index 7f09c2f3af9e940454178de465a535225676ad80..3477b7a6269ed295a59acd10e6b49d8b5e4ca8b6 100644
--- a/core/tests/Drupal/KernelTests/Core/Form/FormDefaultHandlersTest.php
+++ b/core/tests/Drupal/KernelTests/Core/Form/FormDefaultHandlersTest.php
@@ -14,21 +14,6 @@
  */
 class FormDefaultHandlersTest extends KernelTestBase implements FormInterface {
 
-  /**
-   * Modules to enable.
-   *
-   * @var array
-   */
-  protected static $modules = ['system'];
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function setUp(): void {
-    parent::setUp();
-    $this->installSchema('system', ['key_value_expire']);
-  }
-
   /**
    * {@inheritdoc}
    */
diff --git a/core/tests/Drupal/KernelTests/Core/KeyValueStore/DatabaseStorageExpirableTest.php b/core/tests/Drupal/KernelTests/Core/KeyValueStore/DatabaseStorageExpirableTest.php
index b3e45a773f3e190912cf3bb79904e7bccd17451c..cfaa7d13e35f20336e68f440a0fd80c127b1463d 100644
--- a/core/tests/Drupal/KernelTests/Core/KeyValueStore/DatabaseStorageExpirableTest.php
+++ b/core/tests/Drupal/KernelTests/Core/KeyValueStore/DatabaseStorageExpirableTest.php
@@ -22,7 +22,6 @@ class DatabaseStorageExpirableTest extends StorageTestBase {
   protected function setUp(): void {
     parent::setUp();
     $this->factory = 'keyvalue.expirable';
-    $this->installSchema('system', ['key_value_expire']);
   }
 
   /**
diff --git a/core/tests/Drupal/KernelTests/Core/KeyValueStore/DatabaseStorageTest.php b/core/tests/Drupal/KernelTests/Core/KeyValueStore/DatabaseStorageTest.php
index b70fa69fa92b4d4f48e01c56f5bc74c24ad5100b..23332479158736129ae306910312003bd55bf7d2 100644
--- a/core/tests/Drupal/KernelTests/Core/KeyValueStore/DatabaseStorageTest.php
+++ b/core/tests/Drupal/KernelTests/Core/KeyValueStore/DatabaseStorageTest.php
@@ -12,18 +12,6 @@
  */
 class DatabaseStorageTest extends StorageTestBase {
 
-  /**
-   * Modules to enable.
-   *
-   * @var array
-   */
-  protected static $modules = ['system'];
-
-  protected function setUp(): void {
-    parent::setUp();
-    $this->installSchema('system', ['key_value']);
-  }
-
   /**
    * {@inheritdoc}
    */
diff --git a/core/tests/Drupal/KernelTests/Core/KeyValueStore/GarbageCollectionTest.php b/core/tests/Drupal/KernelTests/Core/KeyValueStore/GarbageCollectionTest.php
index 6d774687f970d72f1e502b6467c4c1ac25ec9656..a8a0239110e793ae660cf25e3387537dbbda1278 100644
--- a/core/tests/Drupal/KernelTests/Core/KeyValueStore/GarbageCollectionTest.php
+++ b/core/tests/Drupal/KernelTests/Core/KeyValueStore/GarbageCollectionTest.php
@@ -21,13 +21,6 @@ class GarbageCollectionTest extends KernelTestBase {
    */
   protected static $modules = ['system'];
 
-  protected function setUp(): void {
-    parent::setUp();
-
-    // These additional tables are necessary due to the call to system_cron().
-    $this->installSchema('system', ['key_value_expire']);
-  }
-
   /**
    * Tests garbage collection.
    */
diff --git a/core/tests/Drupal/KernelTests/Core/Queue/QueueSerializationTest.php b/core/tests/Drupal/KernelTests/Core/Queue/QueueSerializationTest.php
index fe6d8a4230334c8969569a7804fe27f8ce271890..2f70eb6a36f0b67b04408f5a65a831863695a234 100644
--- a/core/tests/Drupal/KernelTests/Core/Queue/QueueSerializationTest.php
+++ b/core/tests/Drupal/KernelTests/Core/Queue/QueueSerializationTest.php
@@ -77,7 +77,7 @@ public function submitForm(array &$form, FormStateInterface $form_state) {
    */
   protected function setUp(): void {
     parent::setUp();
-    $this->installSchema('system', ['key_value_expire', 'sequences']);
+    $this->installSchema('system', ['sequences']);
     $this->installEntitySchema('user');
     $this->queue = \Drupal::service('queue.database')->get('aggregator_refresh');
     $test_user = User::create([
diff --git a/core/tests/Drupal/KernelTests/Core/TempStore/AnonymousPrivateTempStoreTest.php b/core/tests/Drupal/KernelTests/Core/TempStore/AnonymousPrivateTempStoreTest.php
index e96549e38f2c995a9e471b3f8bfe50f286a7e248..9820ff89d0f03e6adaf0c0bf7d86dca72ec43e62 100644
--- a/core/tests/Drupal/KernelTests/Core/TempStore/AnonymousPrivateTempStoreTest.php
+++ b/core/tests/Drupal/KernelTests/Core/TempStore/AnonymousPrivateTempStoreTest.php
@@ -32,10 +32,6 @@ class AnonymousPrivateTempStoreTest extends KernelTestBase {
   protected function setUp(): void {
     parent::setUp();
 
-    // Install system tables to test the key/value storage without installing a
-    // full Drupal environment.
-    $this->installSchema('system', ['key_value_expire']);
-
     $request = Request::create('/');
     $stack = $this->container->get('request_stack');
     $stack->pop();
diff --git a/core/tests/Drupal/KernelTests/Core/TempStore/TempStoreDatabaseTest.php b/core/tests/Drupal/KernelTests/Core/TempStore/TempStoreDatabaseTest.php
index dc7f6e20b2f83a8bb3e8d22fe8c35a7e3434f60e..791d79dfab695d978145e3212979170e784a02fd 100644
--- a/core/tests/Drupal/KernelTests/Core/TempStore/TempStoreDatabaseTest.php
+++ b/core/tests/Drupal/KernelTests/Core/TempStore/TempStoreDatabaseTest.php
@@ -16,24 +16,6 @@
  */
 class TempStoreDatabaseTest extends KernelTestBase {
 
-  /**
-   * Modules to enable.
-   *
-   * @var array
-   */
-  protected static $modules = ['system'];
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function setUp(): void {
-    parent::setUp();
-
-    // Install system tables to test the key/value storage without installing a
-    // full Drupal environment.
-    $this->installSchema('system', ['key_value_expire']);
-  }
-
   /**
    * Tests the SharedTempStore API.
    */
diff --git a/core/tests/Drupal/KernelTests/KernelTestBase.php b/core/tests/Drupal/KernelTests/KernelTestBase.php
index f13f2504caee4d7229cf616de1c2513ca2b64736..afe40b747a9d26f26a57ed030871d73fed645135 100644
--- a/core/tests/Drupal/KernelTests/KernelTestBase.php
+++ b/core/tests/Drupal/KernelTests/KernelTestBase.php
@@ -709,6 +709,13 @@ protected function installSchema($module, $tables) {
     }
     $tables = (array) $tables;
     foreach ($tables as $table) {
+      // The tables key_value and key_value_expire are lazy loaded and therefore
+      // no longer have to be created with the installSchema() method.
+      // @see https://www.drupal.org/node/3143286
+      if ($module === 'system' && in_array($table, ['key_value', 'key_value_expire'])) {
+        @trigger_error('Installing the tables key_value and key_value_expire with the method KernelTestBase::installSchema() is deprecated in drupal:9.1.0 and is removed from drupal:10.0.0. The tables are now lazy loaded and therefore will be installed automatically when used. See https://www.drupal.org/node/3143286', E_USER_DEPRECATED);
+        continue;
+      }
       $schema = drupal_get_module_schema($module, $table);
       if (empty($schema)) {
         throw new \LogicException("$module module does not define a schema for table '$table'.");
diff --git a/core/tests/Drupal/KernelTests/KernelTestBaseTest.php b/core/tests/Drupal/KernelTests/KernelTestBaseTest.php
index 40d325b594bdaea4095a649bbe6adcb5267e0a98..8a00387e70e0cb2a85113ab7a4f4bb38e41ae34e 100644
--- a/core/tests/Drupal/KernelTests/KernelTestBaseTest.php
+++ b/core/tests/Drupal/KernelTests/KernelTestBaseTest.php
@@ -328,4 +328,16 @@ public function testAssertIdenticalObject() {
     $this->assertIdenticalObject((object) ['foo' => 'bar'], (object) ['foo' => 'bar']);
   }
 
+  /**
+   * Tests the deprecation of ::installSchema with the tables key_value(_expire).
+   *
+   * @group legacy
+   * @expectedDeprecation Installing the tables key_value and key_value_expire with the method KernelTestBase::installSchema() is deprecated in drupal:9.1.0 and is removed from drupal:10.0.0. The tables are now lazy loaded and therefore will be installed automatically when used. See https://www.drupal.org/node/3143286
+    */
+  public function testKernelTestBaseInstallSchema() {
+    $this->enableModules(['system']);
+    $this->installSchema('system', ['key_value', 'key_value_expire']);
+    $this->assertFalse(Database::getConnection()->schema()->tableExists('key_value'));
+  }
+
 }