diff --git a/core/includes/entity.inc b/core/includes/entity.inc
index 22c2ad4754..5d641b4dd8 100644
--- a/core/includes/entity.inc
+++ b/core/includes/entity.inc
@@ -243,8 +243,10 @@ function entity_load_unchanged($entity_type, $id) {
  * @see \Drupal\Core\Entity\EntityTypeManagerInterface::getStorage()
  * @see \Drupal\Core\Entity\EntityStorageInterface::loadMultiple()
  * @see \Drupal\Core\Entity\EntityStorageInterface::delete()
+ * @see https://www.drupal.org/node/3051072
  */
 function entity_delete_multiple($entity_type, array $ids) {
+  @trigger_error(__FUNCTION__ . ' is deprecated in drupal:8.0.0 and will be removed in drupal:9.0.0. Use the entity storage\'s delete() method to delete multiple entities. @see https://www.drupal.org/node/3051072', E_USER_DEPRECATED);
   $controller = \Drupal::entityManager()->getStorage($entity_type);
   $entities = $controller->loadMultiple($ids);
   $controller->delete($entities);
diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc
index 70aea0d9df..99d30880d3 100644
--- a/core/includes/install.core.inc
+++ b/core/includes/install.core.inc
@@ -1698,7 +1698,10 @@ function install_download_additional_translations_operations(&$install_state) {
       ->save();
     \Drupal::service('language.default')->set($language);
     if (empty($install_state['profile_info']['keep_english'])) {
-      entity_delete_multiple('configurable_language', ['en']);
+      $en = ConfigurableLanguage::load('en');
+      if ($en) {
+        $en->delete();
+      }
     }
   }
 
diff --git a/core/modules/block/tests/src/Functional/BlockTest.php b/core/modules/block/tests/src/Functional/BlockTest.php
index 551eec3e78..f54f7a6831 100644
--- a/core/modules/block/tests/src/Functional/BlockTest.php
+++ b/core/modules/block/tests/src/Functional/BlockTest.php
@@ -456,7 +456,9 @@ public function testBlockCacheTags() {
     $this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'HIT');
 
     // Delete the "Powered by Drupal" blocks; verify a cache miss.
-    entity_delete_multiple('block', ['powered', 'powered-2']);
+    $block_storage = \Drupal::entityTypeManager()->getStorage('block');
+    $block_storage->load('powered')->delete();
+    $block_storage->load('powered-2')->delete();
     $this->drupalGet('<front>');
     $this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'MISS');
   }
diff --git a/core/modules/book/tests/src/Functional/BookTest.php b/core/modules/book/tests/src/Functional/BookTest.php
index 39c856c7e2..972c240ceb 100644
--- a/core/modules/book/tests/src/Functional/BookTest.php
+++ b/core/modules/book/tests/src/Functional/BookTest.php
@@ -353,11 +353,13 @@ public function testBookDelete() {
     $node4 = $node_storage->load($nodes[4]->id());
     $this->assertTrue(empty($node4->book), 'Deleting child book node properly allowed.');
 
+    // $nodes[4] is stale, trying to delete it directly will cause an error.
+    $node4->delete();
+    unset($nodes[4]);
+
     // Delete all child book nodes and retest top-level node deletion.
-    foreach ($nodes as $node) {
-      $nids[] = $node->id();
-    }
-    entity_delete_multiple('node', $nids);
+    $node_storage->delete($nodes);
+
     $this->drupalPostForm('node/' . $this->book->id() . '/outline/remove', $edit, t('Remove'));
     $node_storage->resetCache([$this->book->id()]);
     $node = $node_storage->load($this->book->id());
diff --git a/core/modules/comment/comment.module b/core/modules/comment/comment.module
index ea2cc46d36..12886406db 100644
--- a/core/modules/comment/comment.module
+++ b/core/modules/comment/comment.module
@@ -204,7 +204,9 @@ function comment_field_config_delete(FieldConfigInterface $field) {
     $entity_query->condition('entity_type', $field->getEntityTypeId());
     $entity_query->condition('field_name', $field->getName());
     $cids = $entity_query->execute();
-    entity_delete_multiple('comment', $cids);
+    $comment_storage = \Drupal::entityTypeManager()->getStorage('comment');
+    $comments = $comment_storage->loadMultiple($cids);
+    $comment_storage->delete($comments);
   }
 }
 
@@ -406,7 +408,9 @@ function comment_entity_predelete(EntityInterface $entity) {
     $entity_query->condition('entity_id', (int) $entity->id());
     $entity_query->condition('entity_type', $entity->getEntityTypeId());
     $cids = $entity_query->execute();
-    entity_delete_multiple('comment', $cids);
+    $comment_storage = \Drupal::entityTypeManager()->getStorage('comment');
+    $comments = $comment_storage->loadMultiple($cids);
+    $comment_storage->delete($comments);
     \Drupal::service('comment.statistics')->delete($entity);
   }
 }
@@ -557,7 +561,9 @@ function comment_user_predelete($account) {
   $entity_query = \Drupal::entityQuery('comment');
   $entity_query->condition('uid', $account->id());
   $cids = $entity_query->execute();
-  entity_delete_multiple('comment', $cids);
+  $comment_storage = \Drupal::entityTypeManager()->getStorage('comment');
+  $comments = $comment_storage->loadMultiple($cids);
+  $comment_storage->delete($comments);
 }
 
 /**
diff --git a/core/modules/comment/src/Entity/Comment.php b/core/modules/comment/src/Entity/Comment.php
index bd225d23c1..55c4d85d79 100644
--- a/core/modules/comment/src/Entity/Comment.php
+++ b/core/modules/comment/src/Entity/Comment.php
@@ -189,7 +189,9 @@ public static function postDelete(EntityStorageInterface $storage, array $entiti
     parent::postDelete($storage, $entities);
 
     $child_cids = $storage->getChildCids($entities);
-    entity_delete_multiple('comment', $child_cids);
+    $comment_storage = \Drupal::entityTypeManager()->getStorage('comment');
+    $comments = $comment_storage->loadMultiple($child_cids);
+    $comment_storage->delete($comments);
 
     foreach ($entities as $id => $entity) {
       \Drupal::service('comment.statistics')->update($entity);
diff --git a/core/modules/comment/tests/src/Functional/CommentLinksTest.php b/core/modules/comment/tests/src/Functional/CommentLinksTest.php
index c17ad8e80e..4ce4e1c195 100644
--- a/core/modules/comment/tests/src/Functional/CommentLinksTest.php
+++ b/core/modules/comment/tests/src/Functional/CommentLinksTest.php
@@ -51,7 +51,7 @@ public function testCommentLinks() {
     // Remove additional user permissions from $this->webUser added by setUp(),
     // since this test is limited to anonymous and authenticated roles only.
     $roles = $this->webUser->getRoles();
-    entity_delete_multiple('user_role', [reset($roles)]);
+    \Drupal::entityTypeManager()->getStorage('user_role')->load(reset($roles))->delete();
 
     // Create a comment via CRUD API functionality, since
     // $this->postComment() relies on actual user permissions.
diff --git a/core/modules/comment/tests/src/Functional/CommentNodeChangesTest.php b/core/modules/comment/tests/src/Functional/CommentNodeChangesTest.php
index a63ce8bc05..8229aefd5f 100644
--- a/core/modules/comment/tests/src/Functional/CommentNodeChangesTest.php
+++ b/core/modules/comment/tests/src/Functional/CommentNodeChangesTest.php
@@ -27,7 +27,7 @@ public function testNodeDeletion() {
     $this->assertNotNull(FieldStorageConfig::load('node.comment'), 'Comment field storage exists');
     $this->assertNotNull(FieldConfig::load('node.article.comment'), 'Comment field exists');
     // Delete the node type.
-    entity_delete_multiple('node_type', [$this->node->bundle()]);
+    $this->node->get('type')->entity->delete();
     $this->assertNull(FieldStorageConfig::load('node.comment'), 'Comment field storage deleted');
     $this->assertNull(FieldConfig::load('node.article.comment'), 'Comment field deleted');
   }
diff --git a/core/modules/dblog/tests/src/Functional/DbLogTest.php b/core/modules/dblog/tests/src/Functional/DbLogTest.php
index 0756315ee5..878b809655 100644
--- a/core/modules/dblog/tests/src/Functional/DbLogTest.php
+++ b/core/modules/dblog/tests/src/Functional/DbLogTest.php
@@ -738,7 +738,7 @@ public function testTemporaryUser() {
     $this->assertText('Dblog test log message');
 
     // Delete the user.
-    user_delete($tempuser->id());
+    $tempuser->delete();
     $this->drupalGet('user/' . $tempuser_uid);
     $this->assertResponse(404);
 
diff --git a/core/modules/forum/tests/src/Functional/ForumTest.php b/core/modules/forum/tests/src/Functional/ForumTest.php
index af331916b9..5eeb67cd3b 100644
--- a/core/modules/forum/tests/src/Functional/ForumTest.php
+++ b/core/modules/forum/tests/src/Functional/ForumTest.php
@@ -257,7 +257,9 @@ public function testAddOrphanTopic() {
     $tids = \Drupal::entityQuery('taxonomy_term')
       ->condition('vid', $vid)
       ->execute();
-    entity_delete_multiple('taxonomy_term', $tids);
+    $term_storage = \Drupal::entityTypeManager()->getStorage('taxonomy_term');
+    $terms = $term_storage->loadMultiple($tids);
+    $term_storage->delete($terms);
 
     // Create an orphan forum item.
     $edit = [];
diff --git a/core/modules/language/tests/src/Kernel/LanguageDependencyInjectionTest.php b/core/modules/language/tests/src/Kernel/LanguageDependencyInjectionTest.php
index 287ab95288..45bf085fd7 100644
--- a/core/modules/language/tests/src/Kernel/LanguageDependencyInjectionTest.php
+++ b/core/modules/language/tests/src/Kernel/LanguageDependencyInjectionTest.php
@@ -35,7 +35,8 @@ public function testDependencyInjectedNewLanguage() {
   public function testDependencyInjectedNewDefaultLanguage() {
     $default_language = ConfigurableLanguage::load(\Drupal::languageManager()->getDefaultLanguage()->getId());
     // Change the language default object to different values.
-    ConfigurableLanguage::createFromLangcode('fr')->save();
+    $fr = ConfigurableLanguage::createFromLangcode('fr');
+    $fr->save();
     $this->config('system.site')->set('default_langcode', 'fr')->save();
 
     // The language system creates a Language object which contains the
@@ -45,7 +46,7 @@ public function testDependencyInjectedNewDefaultLanguage() {
 
     // Delete the language to check that we fallback to the default.
     try {
-      entity_delete_multiple('configurable_language', ['fr']);
+      $fr->delete();
       $this->fail('Expected DeleteDefaultLanguageException thrown.');
     }
     catch (DeleteDefaultLanguageException $e) {
@@ -55,7 +56,7 @@ public function testDependencyInjectedNewDefaultLanguage() {
     // Re-save the previous default language and the delete should work.
     $this->config('system.site')->set('default_langcode', $default_language->getId())->save();
 
-    entity_delete_multiple('configurable_language', ['fr']);
+    $fr->delete();
     $result = \Drupal::languageManager()->getCurrentLanguage();
     $this->assertIdentical($result->getId(), $default_language->getId());
   }
diff --git a/core/modules/language/tests/src/Kernel/LanguageFallbackTest.php b/core/modules/language/tests/src/Kernel/LanguageFallbackTest.php
index 17f4ca396f..a6a12fa493 100644
--- a/core/modules/language/tests/src/Kernel/LanguageFallbackTest.php
+++ b/core/modules/language/tests/src/Kernel/LanguageFallbackTest.php
@@ -53,13 +53,13 @@ public function testCandidates() {
     $this->assertEqual(array_values($candidates), $expected, 'Language fallback candidates are alterable for specific operations.');
 
     // Check that when the site is monolingual no language fallback is applied.
-    $langcodes_to_delete = [];
+    /** @var \Drupal\Core\Config\Entity\ConfigEntityStorageInterface $configurable_language_storage */
+    $configurable_language_storage = $this->container->get('entity_type.manager')->getStorage('configurable_language');
     foreach ($language_list as $langcode => $language) {
       if (!$language->isDefault()) {
-        $langcodes_to_delete[] = $langcode;
+        $configurable_language_storage->load($langcode)->delete();
       }
     }
-    entity_delete_multiple('configurable_language', $langcodes_to_delete);
     $candidates = $this->languageManager->getFallbackCandidates();
     $this->assertEqual(array_values($candidates), [LanguageInterface::LANGCODE_DEFAULT], 'Language fallback is not applied when the Language module is not enabled.');
   }
diff --git a/core/modules/node/node.module b/core/modules/node/node.module
index a622cc1f7e..dfe5370faf 100644
--- a/core/modules/node/node.module
+++ b/core/modules/node/node.module
@@ -791,9 +791,10 @@ function node_user_predelete($account) {
     ->condition('uid', $account->id())
     ->accessCheck(FALSE)
     ->execute();
-  entity_delete_multiple('node', $nids);
   // Delete old revisions.
   $storage_controller = \Drupal::entityManager()->getStorage('node');
+  $nodes = $storage_controller->loadMultiple($nids);
+  $storage_controller->delete($nodes);
   $revisions = $storage_controller->userRevisionIds($account);
   foreach ($revisions as $revision) {
     node_revision_delete($revision);
diff --git a/core/modules/shortcut/tests/src/Functional/ShortcutLinksTest.php b/core/modules/shortcut/tests/src/Functional/ShortcutLinksTest.php
index 238ee4fa9b..093aa5689a 100644
--- a/core/modules/shortcut/tests/src/Functional/ShortcutLinksTest.php
+++ b/core/modules/shortcut/tests/src/Functional/ShortcutLinksTest.php
@@ -290,7 +290,8 @@ public function testShortcutLinkDelete() {
     $this->assertFalse(in_array($shortcut->id(), $ids), 'Successfully deleted a shortcut.');
 
     // Delete all the remaining shortcut links.
-    entity_delete_multiple('shortcut', array_filter($ids));
+    $storage = \Drupal::entityTypeManager()->getStorage('shortcut');
+    $storage->delete($storage->loadMultiple(array_filter($ids)));
 
     // Get the front page to check that no exceptions occur.
     $this->drupalGet('');
diff --git a/core/modules/taxonomy/src/Entity/Vocabulary.php b/core/modules/taxonomy/src/Entity/Vocabulary.php
index a7a23292f5..015eb611dd 100644
--- a/core/modules/taxonomy/src/Entity/Vocabulary.php
+++ b/core/modules/taxonomy/src/Entity/Vocabulary.php
@@ -125,7 +125,9 @@ public static function preDelete(EntityStorageInterface $storage, array $entitie
     parent::preDelete($storage, $entities);
 
     // Only load terms without a parent, child terms will get deleted too.
-    entity_delete_multiple('taxonomy_term', $storage->getToplevelTids(array_keys($entities)));
+    $term_storage = \Drupal::entityTypeManager()->getStorage('taxonomy_term');
+    $terms = $term_storage->loadMultiple($storage->getToplevelTids(array_keys($entities)));
+    $term_storage->delete($terms);
   }
 
   /**
diff --git a/core/modules/taxonomy/tests/src/Kernel/TermKernelTest.php b/core/modules/taxonomy/tests/src/Kernel/TermKernelTest.php
index e156f1ca7d..4e1eaafa1e 100644
--- a/core/modules/taxonomy/tests/src/Kernel/TermKernelTest.php
+++ b/core/modules/taxonomy/tests/src/Kernel/TermKernelTest.php
@@ -30,8 +30,7 @@ protected function setUp() {
   }
 
   /**
-   * Deleting terms should also remove related vocabulary.
-   * Deleting an invalid term should silently fail.
+   * Tests that a deleted term is no longer in the vocabulary.
    */
   public function testTermDelete() {
     $vocabulary = $this->createVocabulary();
@@ -40,9 +39,6 @@ public function testTermDelete() {
     $valid_term->delete();
     $terms = \Drupal::entityTypeManager()->getStorage('taxonomy_term')->loadByProperties(['vid' => $vocabulary->id()]);
     $this->assertTrue(empty($terms), 'Vocabulary is empty after deletion');
-
-    // Delete an invalid term. Should not throw any notices.
-    entity_delete_multiple('taxonomy_term', [42]);
   }
 
   /**
diff --git a/core/modules/user/tests/src/Kernel/UserDeleteTest.php b/core/modules/user/tests/src/Kernel/UserDeleteTest.php
index a015d70483..928c095ec2 100644
--- a/core/modules/user/tests/src/Kernel/UserDeleteTest.php
+++ b/core/modules/user/tests/src/Kernel/UserDeleteTest.php
@@ -53,7 +53,9 @@ public function testUserDeleteMultiple() {
     // We should be able to load one of the users.
     $this->assertNotNull(User::load($user_a->id()));
     // Delete the users.
-    user_delete_multiple($uids);
+    $storage = $this->container->get('entity_type.manager')->getStorage('user');
+    $users = $storage->loadMultiple($uids);
+    $storage->delete($users);
     // Test if the roles assignments are deleted.
     $query = $connection->select('user__roles', 'r');
     $roles_after_deletion = $query
diff --git a/core/modules/user/tests/src/Kernel/UserLegacyTest.php b/core/modules/user/tests/src/Kernel/UserLegacyTest.php
index cdf4e9751f..46abae4aa4 100644
--- a/core/modules/user/tests/src/Kernel/UserLegacyTest.php
+++ b/core/modules/user/tests/src/Kernel/UserLegacyTest.php
@@ -27,6 +27,7 @@ class UserLegacyTest extends KernelTestBase {
   protected function setUp() {
     parent::setUp();
     $this->installEntitySchema('user');
+    $this->installSchema('user', ['users_data']);
   }
 
   /**
@@ -59,4 +60,28 @@ public function testUserView() {
     $this->assertEquals(4, count(user_view_multiple($entities)));
   }
 
+  /**
+   * Tests that user_delete throws a deprecation error.
+   *
+   * @expectedDeprecation user_delete() is deprecated in drupal:8.8.0. Use the user entity's delete method to delete the user. See https://www.drupal.org/node/3051463
+   */
+  public function testUserDelete() {
+    User::create(['name' => 'foo', 'uid' => 10])->save();
+    user_delete(10);
+    $this->assert(NULL === User::load(10), "User has been deleted");
+  }
+
+  /**
+   * Tests that user_delete_multiple throws a deprecation error.
+   *
+   * @expectedDeprecation user_delete_multiple() is deprecated in drupal:8.8.0. Use the entity storage system to delete the users. See https://www.drupal.org/node/3051463
+   */
+  public function testUserDeleteMultiple() {
+    User::create(['name' => 'foo', 'uid' => 10])->save();
+    User::create(['name' => 'bar', 'uid' => 11])->save();
+    user_delete_multiple([10, 11]);
+    $this->assert(NULL === User::load(10), "User 10 has been deleted");
+    $this->assert(NULL === User::load(11), "User 11 has been deleted");
+  }
+
 }
diff --git a/core/modules/user/user.module b/core/modules/user/user.module
index e275dcbdf7..772c4e23b9 100644
--- a/core/modules/user/user.module
+++ b/core/modules/user/user.module
@@ -864,8 +864,17 @@ function user_cancel_methods() {
  *
  * @param int $uid
  *   A user ID.
+ *
+ * @deprecated in drupal:8.8.0 and will be removed from drupal:9.0.0. Use the user
+ *   entity's delete method to delete the user.
+ * @code
+ *   Drupal::entityTypeManager->getStorage('user')->load($uid)->delete();
+ * @endcode
+ *
+ * @see https://www.drupal.org/node/3051463
  */
 function user_delete($uid) {
+  @trigger_error("user_delete() is deprecated in drupal:8.8.0. Use the user entity's delete method to delete the user. See https://www.drupal.org/node/3051463", E_USER_DEPRECATED);
   user_delete_multiple([$uid]);
 }
 
@@ -875,10 +884,18 @@ function user_delete($uid) {
  * @param int[] $uids
  *   An array of user IDs.
  *
- * @see hook_ENTITY_TYPE_predelete()
- * @see hook_ENTITY_TYPE_delete()
+ * @deprecated in drupal:8.8.0 and will be removed from drupal:9.0.0. Use the
+ *   entity storage system to delete the users.
+ * @code
+ *   $storage_handler = \Drupal::entityTypeManager()->getStorage('user');
+ *   $users = $storage_handler->loadMultiple($uids);
+ *   $storage_handler->delete($users);
+ * @endcode
+ *
+ * @see https://www.drupal.org/node/3051463
  */
 function user_delete_multiple(array $uids) {
+  @trigger_error("user_delete_multiple() is deprecated in drupal:8.8.0. Use the entity storage system to delete the users. See https://www.drupal.org/node/3051463", E_USER_DEPRECATED);
   entity_delete_multiple('user', $uids);
 }
 
diff --git a/core/tests/Drupal/KernelTests/Core/Entity/EntityApiTest.php b/core/tests/Drupal/KernelTests/Core/Entity/EntityApiTest.php
index 23d1734b74..8a45ed94c5 100644
--- a/core/tests/Drupal/KernelTests/Core/Entity/EntityApiTest.php
+++ b/core/tests/Drupal/KernelTests/Core/Entity/EntityApiTest.php
@@ -86,8 +86,8 @@ protected function assertCRUD($entity_type, UserInterface $user1) {
     $this->assertEqual($entity->name->value, 'test3', format_string('%entity_type: Entity updated.', ['%entity_type' => $entity_type]));
 
     // Try deleting multiple test entities by deleting all.
-    $ids = array_keys($storage->loadMultiple());
-    entity_delete_multiple($entity_type, $ids);
+    $entities = $storage->loadMultiple();
+    $storage->delete($entities);
 
     $all = $storage->loadMultiple();
     $this->assertTrue(empty($all), format_string('%entity_type: Deleted all entities.', ['%entity_type' => $entity_type]));
diff --git a/core/tests/Drupal/KernelTests/Core/Entity/EntityCrudHookTest.php b/core/tests/Drupal/KernelTests/Core/Entity/EntityCrudHookTest.php
index df9880714f..a3566fdd6c 100644
--- a/core/tests/Drupal/KernelTests/Core/Entity/EntityCrudHookTest.php
+++ b/core/tests/Drupal/KernelTests/Core/Entity/EntityCrudHookTest.php
@@ -524,7 +524,7 @@ public function testUserHooks() {
     ]);
 
     $GLOBALS['entity_crud_hook_test'] = [];
-    user_delete($account->id());
+    $account->delete();
 
     $this->assertHookMessageOrder([
       'entity_crud_hook_test_user_predelete called',
diff --git a/core/tests/Drupal/KernelTests/Core/Entity/EntityLegacyTest.php b/core/tests/Drupal/KernelTests/Core/Entity/EntityLegacyTest.php
index cf4ea64b95..ca502d4425 100644
--- a/core/tests/Drupal/KernelTests/Core/Entity/EntityLegacyTest.php
+++ b/core/tests/Drupal/KernelTests/Core/Entity/EntityLegacyTest.php
@@ -34,6 +34,21 @@ protected function setUp() {
     $this->installEntitySchema('entity_test_rev');
   }
 
+  /**
+   * Tests that entity_delete_multiple triggers an error.
+   *
+   * @expectedDeprecation entity_delete_multiple is deprecated in drupal:8.0.0 and will be removed in drupal:9.0.0. Use the entity storage's delete() method to delete multiple entities. @see https://www.drupal.org/node/3051072
+   *
+   * @throws \Drupal\Core\Entity\EntityStorageException
+   */
+  public function testEntityDeleteMultiple() {
+    EntityTest::create(['name' => 'published entity'])->save();
+    EntityTest::create(['name' => 'published entity'])->save();
+    $this->assertCount(2, \Drupal::entityTypeManager()->getStorage('entity_test')->loadMultiple());
+    entity_delete_multiple('entity_test', [1, 2]);
+    $this->assertCount(0, \Drupal::entityTypeManager()->getStorage('entity_test')->loadMultiple());
+  }
+
   /**
    * @expectedDeprecation entity_load_multiple() is deprecated in Drupal 8.0.0 and will be removed before Drupal 9.0.0. Use the entity type storage's loadMultiple() method. See https://www.drupal.org/node/2266845
    * @expectedDeprecation entity_load() is deprecated in Drupal 8.0.0 and will be removed before Drupal 9.0.0. Use the entity type storage's load() method. See https://www.drupal.org/node/2266845
