diff --git a/core/includes/entity.inc b/core/includes/entity.inc
index 9f4a7c1128..f62ec66728 100644
--- a/core/includes/entity.inc
+++ b/core/includes/entity.inc
@@ -263,8 +263,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..328c32bfca 100644
--- a/core/includes/install.core.inc
+++ b/core/includes/install.core.inc
@@ -1698,7 +1698,7 @@ 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']);
+      ConfigurableLanguage::load('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 88e3246260..7cb39219ef 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);
   }
 }
 
@@ -397,7 +399,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);
   }
 }
@@ -548,7 +552,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..2fbe6a7200 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()]);
+    \Drupal::entityTypeManager()->getStorage('node_type')->load($this->node->bundle())->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/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 0be08b45dc..c4b26b9eb8 100644
--- a/core/modules/node/node.module
+++ b/core/modules/node/node.module
@@ -789,9 +789,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..4cedd291b8 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 = $this->container->get('entity_type.manager')->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 9d0cf90e7a..1b7bff64dd 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 cb1930b4bd..6366c369c7 100644
--- a/core/modules/taxonomy/tests/src/Kernel/TermKernelTest.php
+++ b/core/modules/taxonomy/tests/src/Kernel/TermKernelTest.php
@@ -31,7 +31,6 @@ protected function setUp() {
 
   /**
    * Deleting terms should also remove related vocabulary.
-   * Deleting an invalid term should silently fail.
    */
   public function testTermDelete() {
     $vocabulary = $this->createVocabulary();
@@ -40,9 +39,6 @@ public function testTermDelete() {
     $valid_term->delete();
     $terms = entity_load_multiple_by_properties('taxonomy_term', ['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/user.module b/core/modules/user/user.module
index ef9ba7bafa..27295143ec 100644
--- a/core/modules/user/user.module
+++ b/core/modules/user/user.module
@@ -879,7 +879,9 @@ function user_delete($uid) {
  * @see hook_ENTITY_TYPE_delete()
  */
 function user_delete_multiple(array $uids) {
-  entity_delete_multiple('user', $uids);
+  $user_storage = \Drupal::entityTypeManager()->getStorage('user');
+  $users = $user_storage->loadMultiple($uids);
+  $user_storage->delete($users);
 }
 
 /**
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/EntityLegacyTest.php b/core/tests/Drupal/KernelTests/Core/Entity/EntityLegacyTest.php
index 1130611a9a..ebd63f3436 100644
--- a/core/tests/Drupal/KernelTests/Core/Entity/EntityLegacyTest.php
+++ b/core/tests/Drupal/KernelTests/Core/Entity/EntityLegacyTest.php
@@ -67,4 +67,19 @@ public function testLegacyDisplayFunctions() {
     $this->assertEquals('entity_test.entity_test.default', $form_display->id());
   }
 
+  /**
+   * 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());
+  }
+
 }
