diff --git a/core/modules/aggregator/lib/Drupal/aggregator/Entity/Feed.php b/core/modules/aggregator/lib/Drupal/aggregator/Entity/Feed.php
index 24430b9..85e6164 100644
--- a/core/modules/aggregator/lib/Drupal/aggregator/Entity/Feed.php
+++ b/core/modules/aggregator/lib/Drupal/aggregator/Entity/Feed.php
@@ -7,12 +7,14 @@
 
 namespace Drupal\aggregator\Entity;
 
+use Drupal\block\BlockPluginEvents;
 use Drupal\Core\Entity\ContentEntityBase;
 use Drupal\Core\Entity\EntityTypeInterface;
 use Drupal\Core\Field\FieldDefinition;
 use Symfony\Component\DependencyInjection\Container;
 use Drupal\Core\Entity\EntityStorageInterface;
 use Drupal\aggregator\FeedInterface;
+use Symfony\Component\EventDispatcher\GenericEvent;
 
 /**
  * Defines the aggregator feed entity class.
@@ -108,14 +110,10 @@ public static function preDelete(EntityStorageInterface $storage, array $entitie
    */
   public static function postDelete(EntityStorageInterface $storage, array $entities) {
     if (\Drupal::moduleHandler()->moduleExists('block')) {
-      // Make sure there are no active blocks for these feeds.
-      $ids = \Drupal::entityQuery('block')
-        ->condition('plugin', 'aggregator_feed_block')
-        ->condition('settings.feed', array_keys($entities))
-        ->execute();
-      if ($ids) {
-        $block_storage = \Drupal::entityManager()->getStorage('block');
-        $block_storage->delete($block_storage->loadMultiple($ids));
+      foreach ($entities as $entity) {
+        $event = new GenericEvent('aggregator_feed_block', array('conditions' => array('settings.feed' => $entity->id())));
+        \Drupal::service('event_dispatcher')
+          ->dispatch(BlockPluginEvents::PERMANENTLY_UNAVAILABLE, $event);
       }
     }
   }
diff --git a/core/modules/aggregator/lib/Drupal/aggregator/Tests/AggregatorRenderingTest.php b/core/modules/aggregator/lib/Drupal/aggregator/Tests/AggregatorRenderingTest.php
index 161d215..4572345 100644
--- a/core/modules/aggregator/lib/Drupal/aggregator/Tests/AggregatorRenderingTest.php
+++ b/core/modules/aggregator/lib/Drupal/aggregator/Tests/AggregatorRenderingTest.php
@@ -75,6 +75,17 @@ public function testBlockLinks() {
     // Check that the block is no longer displayed.
     $this->drupalGet('test-page');
     $this->assertNoText($block->label(), 'Feed block is not displayed on the page when number of items is set to 0.');
+
+    // Set the number of news items to 5 to test that the block shows again.
+    $feed->block = 5;
+    $feed->save();
+    $this->drupalGet('test-page');
+    $this->assertText($block->label(), 'Feed block is displayed again on the page when number of items is set to 5.');
+
+    // Delete the feed and check that the block is no longer displayed.
+    $feed->delete();
+    $this->drupalGet('test-page');
+    $this->assertNoText($block->label(), 'Feed block is not displayed on the page once deleted.');
   }
 
   /**
diff --git a/core/modules/block/block.services.yml b/core/modules/block/block.services.yml
index 51acbfc..aa49fc0 100644
--- a/core/modules/block/block.services.yml
+++ b/core/modules/block/block.services.yml
@@ -2,7 +2,14 @@ services:
   plugin.manager.block:
     class: Drupal\block\BlockManager
     arguments: ['@container.namespaces', '@cache.discovery', '@language_manager', '@module_handler', '@string_translation']
+    tags:
+      - { name: event_subscriber }
   theme.negotiator.block.admin_demo:
     class: Drupal\block\Theme\AdminDemoNegotiator
     tags:
       - { name: theme_negotiator, priority: 1000 }
+  block.entity.event.subscriber:
+    class: Drupal\block\BlockEntityBlockEventSubscriber
+    arguments: ['@entity.query', '@entity.manager']
+    tags:
+      - { name: event_subscriber }
diff --git a/core/modules/block/custom_block/lib/Drupal/custom_block/Entity/CustomBlock.php b/core/modules/block/custom_block/lib/Drupal/custom_block/Entity/CustomBlock.php
index 71913b7..9f3975b 100644
--- a/core/modules/block/custom_block/lib/Drupal/custom_block/Entity/CustomBlock.php
+++ b/core/modules/block/custom_block/lib/Drupal/custom_block/Entity/CustomBlock.php
@@ -7,11 +7,13 @@
 
 namespace Drupal\custom_block\Entity;
 
+use Drupal\block\BlockPluginEvents;
 use Drupal\Core\Entity\ContentEntityBase;
 use Drupal\Core\Entity\EntityStorageInterface;
 use Drupal\Core\Entity\EntityTypeInterface;
 use Drupal\Core\Field\FieldDefinition;
 use Drupal\custom_block\CustomBlockInterface;
+use Symfony\Component\EventDispatcher\GenericEvent;
 
 /**
  * Defines the custom block entity class.
@@ -138,9 +140,8 @@ public function preSaveRevision(EntityStorageInterface $storage, \stdClass $reco
    * {@inheritdoc}
    */
   public function delete() {
-    foreach ($this->getInstances() as $instance) {
-      $instance->delete();
-    }
+    $event = new GenericEvent('custom_block:' . $this->uuid->value);
+    \Drupal::service('event_dispatcher')->dispatch(BlockPluginEvents::PERMANENTLY_UNAVAILABLE, $event);
     parent::delete();
   }
 
diff --git a/core/modules/block/lib/Drupal/block/BlockEntityBlockEventSubscriber.php b/core/modules/block/lib/Drupal/block/BlockEntityBlockEventSubscriber.php
new file mode 100644
index 0000000..7d997de
--- /dev/null
+++ b/core/modules/block/lib/Drupal/block/BlockEntityBlockEventSubscriber.php
@@ -0,0 +1,75 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\block\BlockEntityBlockEventSubscriber.
+ */
+
+namespace Drupal\block;
+
+use Drupal\Core\Entity\EntityManager;
+use Drupal\Core\Entity\EntityManagerInterface;
+use Drupal\Core\Entity\EntityStorageControllerInterface;
+use Drupal\Core\Entity\Query\QueryFactory;
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
+use Symfony\Component\EventDispatcher\GenericEvent;
+
+/**
+ * Contains block entity responses to block plugin events.
+ */
+class BlockEntityBlockEventSubscriber implements EventSubscriberInterface {
+
+  /**
+   * The entity query factory.
+   *
+   * @var \Drupal\Core\Entity\Query\QueryFactory
+   */
+  protected $queryFactory;
+
+  /**
+   * The block storage controller.
+   *
+   * @var \Drupal\Core\Entity\EntityStorageInterface
+   */
+  protected $blockStorageController;
+
+  /**
+   * Constructs a \Drupal\block\BlockEntityBlockEventSubscriber object.
+   *
+   * @param \Drupal\Core\Entity\Query\QueryFactory $query_factory
+   *   The entity query factory.
+   * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
+   *   The entity manager.
+   */
+  public function __construct(QueryFactory $query_factory, EntityManagerInterface $entity_manager) {
+    $this->queryFactory = $query_factory;
+    $this->blockStorageController = $entity_manager->getStorage('block');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getSubscribedEvents() {
+    $events[BlockPluginEvents::PERMANENTLY_UNAVAILABLE][] = 'deleteEntityByPlugin';
+    return $events;
+  }
+
+  /**
+   * Reacts on removing a block plugin.
+   */
+  public function deleteEntityByPlugin(GenericEvent $event) {
+    $plugin_id = $event->getSubject();
+    $query = $this->queryFactory->get('block');
+    $query->condition('plugin', $plugin_id);
+    if ($event->hasArgument('conditions') && $conditions = $event->getArgument('conditions')) {
+      foreach ($conditions as $condition => $value) {
+        $query->condition($condition, $value);
+      }
+    }
+    $result = $query->execute();
+    if ($blocks = $this->blockStorageController->loadMultiple($result)) {
+      $this->blockStorageController->delete($blocks);
+    }
+  }
+
+}
diff --git a/core/modules/block/lib/Drupal/block/BlockManager.php b/core/modules/block/lib/Drupal/block/BlockManager.php
index 4a1651b..a84c801 100644
--- a/core/modules/block/lib/Drupal/block/BlockManager.php
+++ b/core/modules/block/lib/Drupal/block/BlockManager.php
@@ -13,6 +13,8 @@
 use Drupal\Core\Plugin\DefaultPluginManager;
 use Drupal\Core\StringTranslation\TranslationInterface;
 use Drupal\Core\StringTranslation\StringTranslationTrait;
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
+use Symfony\Component\EventDispatcher\GenericEvent;
 
 /**
  * Manages discovery and instantiation of block plugins.
@@ -21,7 +23,7 @@
  *
  * @see \Drupal\block\BlockPluginInterface
  */
-class BlockManager extends DefaultPluginManager implements BlockManagerInterface {
+class BlockManager extends DefaultPluginManager implements BlockManagerInterface, EventSubscriberInterface {
 
   use StringTranslationTrait;
 
@@ -116,4 +118,22 @@ public function getSortedDefinitions() {
     return $definitions;
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public static function getSubscribedEvents() {
+    $events[BlockPluginEvents::PERMANENTLY_UNAVAILABLE][] = 'blockPluginRemoved';
+    return $events;
+  }
+
+  /**
+   * Reacts on removing a block plugin.
+   *
+   * @param \Symfony\Component\EventDispatcher\GenericEvent $event
+   *   The event containing the plugin ID which is updated.
+   */
+  public function blockPluginRemoved(GenericEvent $event) {
+    $this->clearCachedDefinitions();
+  }
+
 }
diff --git a/core/modules/block/lib/Drupal/block/BlockPluginEvents.php b/core/modules/block/lib/Drupal/block/BlockPluginEvents.php
new file mode 100644
index 0000000..29dce73
--- /dev/null
+++ b/core/modules/block/lib/Drupal/block/BlockPluginEvents.php
@@ -0,0 +1,30 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\block\BlockPluginEvents.
+ */
+
+namespace Drupal\block;
+
+/**
+ * Contains events fired when a block plugin instance becomes unavailable.
+ */
+class BlockPluginEvents {
+
+  /**
+   * This event is thrown when a block plugin is temporary unavailable.
+   *
+   * This could be the case, when something is disabled but not deleted.
+   */
+  const TEMPORARILY_UNAVAILABLE = 'block.unavailable.temporarily';
+
+  /**
+   * This event is thrown when a block plugin is permanently unavailable.
+   *
+   * This could be the case, when a module has been uninstalled or the data
+   * from which a block plugin was derived was deleted.
+   */
+  const PERMANENTLY_UNAVAILABLE = 'block.unavailable.permanently';
+
+}
diff --git a/core/modules/block/lib/Drupal/block/Plugin/views/display/Block.php b/core/modules/block/lib/Drupal/block/Plugin/views/display/Block.php
index 9ee2ca9..43b59e2 100644
--- a/core/modules/block/lib/Drupal/block/Plugin/views/display/Block.php
+++ b/core/modules/block/lib/Drupal/block/Plugin/views/display/Block.php
@@ -8,10 +8,13 @@
 
 namespace Drupal\block\Plugin\views\display;
 
+use Drupal\block\BlockPluginEvents;
 use Drupal\Component\Utility\String;
 use Drupal\views\Plugin\Block\ViewsBlock;
 use Drupal\views\Plugin\views\display\DisplayPluginBase;
-use Drupal\views\Views;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+use Symfony\Component\EventDispatcher\EventDispatcherInterface;
+use Symfony\Component\EventDispatcher\GenericEvent;
 
 /**
  * The plugin that handles a block.
@@ -41,6 +44,42 @@ class Block extends DisplayPluginBase {
    */
   protected $usesAttachments = TRUE;
 
+  /**
+   * The event dispatcher.
+   *
+   * @var \Symfony\Component\EventDispatcher\EventDispatcherInterface
+   */
+  protected $eventDispatcher;
+
+  /**
+   * Constructs a Block object.
+   *
+   * @param array $configuration
+   *   A configuration array containing information about the plugin instance.
+   * @param string $plugin_id
+   *   The plugin_id for the plugin instance.
+   * @param array $plugin_definition
+   *   The plugin implementation definition.
+   * @param \Symfony\Component\EventDispatcher\EventDispatcherInterface
+   */
+  public function __construct(array $configuration, $plugin_id, array $plugin_definition, EventDispatcherInterface $event_dispatcher) {
+    parent::__construct($configuration, $plugin_id, $plugin_definition);
+
+    $this->eventDispatcher = $event_dispatcher;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
+    return new static(
+      $configuration,
+      $plugin_id,
+      $plugin_definition,
+      $container->get('event_dispatcher')
+    );
+  }
+
   protected function defineOptions() {
     $options = parent::defineOptions();
 
@@ -317,15 +356,14 @@ public function usesExposed() {
     }
 
   /**
-   * Overrides \Drupal\views\Plugin\views\display\DisplayPluginBase::remove().
+   * {@inheritdoc}
    */
   public function remove() {
     parent::remove();
 
     $plugin_id = 'views_block:' . $this->view->storage->id() . '-' . $this->display['id'];
-    foreach (entity_load_multiple_by_properties('block', array('plugin' => $plugin_id)) as $block) {
-      $block->delete();
-    }
+    $event = new GenericEvent($plugin_id);
+    $this->eventDispatcher->dispatch(BlockPluginEvents::PERMANENTLY_UNAVAILABLE, $event);
   }
 
 }
diff --git a/core/modules/block/tests/lib/Drupal/block_test/Plugin/Type/BlockManagerTest.php b/core/modules/block/tests/lib/Drupal/block_test/Plugin/Type/BlockManagerTest.php
new file mode 100644
index 0000000..b5d5691
--- /dev/null
+++ b/core/modules/block/tests/lib/Drupal/block_test/Plugin/Type/BlockManagerTest.php
@@ -0,0 +1,51 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\block_test\Plugin\Type\BlockManagerTest.
+ */
+
+namespace Drupal\block_test\Plugin\Type;
+
+use Drupal\block\BlockPluginEvents;
+use Drupal\block\Plugin\Type\BlockManager;
+use Drupal\Tests\UnitTestCase;
+use Symfony\Component\EventDispatcher\EventDispatcher;
+use Symfony\Component\EventDispatcher\GenericEvent;
+
+/**
+ * Tests the block plugin manager.
+ *
+ * @see \Drupal\block\Plugin\Type\BlockManager
+ */
+class BlockManagerTest extends UnitTestCase {
+
+  public static function getInfo() {
+    return array(
+      'name' => 'Block Plugin Event Test',
+      'description' => 'Tests block event responses.',
+      'group' => 'Block',
+    );
+  }
+
+  /**
+   * Tests the reaction when firing block plugin events.
+   */
+  public function testBlockPluginEvents() {
+    $event_dispatcher = new EventDispatcher();
+
+    $block_manager = $this->getMockBuilder('Drupal\block\Plugin\Type\BlockManager')
+      ->disableOriginalConstructor()
+      ->setMethods(array('clearCachedDefinitions'))
+      ->getMock();
+
+    $block_manager->expects($this->once())
+      ->method('clearCachedDefinitions');
+
+    $event_dispatcher->addSubscriber($block_manager);
+    $event = new GenericEvent('test_plugin_id');
+
+    $event_dispatcher->dispatch(BlockPluginEvents::PERMANENTLY_UNAVAILABLE, $event);
+  }
+
+}
diff --git a/core/modules/menu_ui/menu_ui.module b/core/modules/menu_ui/menu_ui.module
index b12baee..045211e 100644
--- a/core/modules/menu_ui/menu_ui.module
+++ b/core/modules/menu_ui/menu_ui.module
@@ -11,11 +11,13 @@
  * URLs to be added to the main site navigation menu.
  */
 
+use Drupal\block\BlockPluginEvents;
 use Drupal\Core\Entity\EntityInterface;
 use Drupal\block\BlockPluginInterface;
 use Drupal\Core\Render\Element;
 use Drupal\node\NodeTypeInterface;
 use Drupal\system\Entity\Menu;
+use Symfony\Component\EventDispatcher\GenericEvent;
 use Symfony\Component\HttpFoundation\JsonResponse;
 use Drupal\menu_link\Entity\MenuLink;
 use Drupal\menu_link\MenuLinkStorage;
@@ -191,9 +193,11 @@ function menu_ui_menu_predelete(Menu $menu) {
 function menu_ui_menu_delete(Menu $menu) {
   menu_cache_clear_all();
 
-  // Invalidate the block cache to update menu-based derivatives.
-  if (\Drupal::moduleHandler()->moduleExists('block')) {
-    \Drupal::service('plugin.manager.block')->clearCachedDefinitions();
+  // Inform the block plugin system that a menu has been deleted.
+  if (Drupal::moduleHandler()->moduleExists('block')) {
+    $event = new GenericEvent('menu_menu_block:' . $menu->id());
+    Drupal::service('event_dispatcher')
+      ->dispatch(BlockPluginEvents::PERMANENTLY_UNAVAILABLE, $event);
   }
 }
 
