diff --git a/core/modules/aggregator/lib/Drupal/aggregator/Entity/Feed.php b/core/modules/aggregator/lib/Drupal/aggregator/Entity/Feed.php
index cf467da..59b8d2e 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\EntityStorageControllerInterface;
 use Drupal\aggregator\FeedInterface;
+use Symfony\Component\EventDispatcher\GenericEvent;
 
 /**
  * Defines the aggregator feed entity class.
@@ -106,14 +108,9 @@ public static function preDelete(EntityStorageControllerInterface $storage_contr
    */
   public static function postDelete(EntityStorageControllerInterface $storage_controller, 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()->getStorageController('block');
-        $block_storage->delete($block_storage->loadMultiple($ids));
+      foreach ($entities as $entity) {
+        $event = new GenericEvent('aggregator_feed_block:' . $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 34293d9..c913ae8 100644
--- a/core/modules/block/block.services.yml
+++ b/core/modules/block/block.services.yml
@@ -2,6 +2,8 @@ services:
   plugin.manager.block:
     class: Drupal\block\Plugin\Type\BlockManager
     arguments: ['@container.namespaces', '@cache.block', '@language_manager', '@module_handler', '@string_translation']
+    tags:
+      - { name: event_subscriber }
   cache.block:
     class: Drupal\Core\Cache\CacheBackendInterface
     tags:
@@ -13,3 +15,8 @@ services:
     class: Drupal\block\Theme\AdminDemoNegotiator
     tags:
       - { name: theme_negotiator, priority: 1000 }
+  block.entity.event.subscriber:
+    class: Drupal\block\BlockEntityBlockEventSubscriber
+    arguments: ['@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 88d232b..b6a2336 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\EntityStorageControllerInterface;
 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.
@@ -145,9 +147,8 @@ public function preSaveRevision(EntityStorageControllerInterface $storage_contro
    * {@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..c2a0fa8
--- /dev/null
+++ b/core/modules/block/lib/Drupal/block/BlockEntityBlockEventSubscriber.php
@@ -0,0 +1,55 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\block\BlockEntityBlockEventSubscriber.
+ */
+
+namespace Drupal\block;
+
+use Drupal\Core\Entity\EntityManager;
+use Drupal\Core\Entity\EntityStorageControllerInterface;
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
+use Symfony\Component\EventDispatcher\GenericEvent;
+
+/**
+ * Contains block entity responses to block plugin events.
+ */
+class BlockEntityBlockEventSubscriber implements EventSubscriberInterface {
+
+  /**
+   * The block storage controller.
+   *
+   * @var \Drupal\Core\Entity\EntityStorageControllerInterface
+   */
+  private $blockStorageController;
+
+  /**
+   * Constructs a \Drupal\block\BlockEntityBlockEventSubscriber object.
+   *
+   * @param \Drupal\Core\Entity\EntityManager $entity_manager
+   *   The entity manager.
+   */
+  function __construct(EntityManager $entity_manager) {
+    $this->blockStorageController = $entity_manager->getStorageController('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();
+    if ($blocks = $this->blockStorageController->loadByProperties(array('plugin' => $plugin_id))) {
+      $this->blockStorageController->delete($blocks);
+    }
+  }
+
+}
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/Type/BlockManager.php b/core/modules/block/lib/Drupal/block/Plugin/Type/BlockManager.php
index 980a59f..6971ab6 100644
--- a/core/modules/block/lib/Drupal/block/Plugin/Type/BlockManager.php
+++ b/core/modules/block/lib/Drupal/block/Plugin/Type/BlockManager.php
@@ -7,11 +7,14 @@
 
 namespace Drupal\block\Plugin\Type;
 
+use Drupal\block\BlockPluginEvents;
 use Drupal\Core\Cache\CacheBackendInterface;
 use Drupal\Core\Extension\ModuleHandlerInterface;
 use Drupal\Core\Language\LanguageManager;
 use Drupal\Core\Plugin\DefaultPluginManager;
 use Drupal\Core\StringTranslation\TranslationInterface;
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
+use Symfony\Component\EventDispatcher\GenericEvent;
 
 /**
  * Manages discovery and instantiation of block plugins.
@@ -20,7 +23,7 @@
  *
  * @see \Drupal\block\BlockPluginInterface
  */
-class BlockManager extends DefaultPluginManager {
+class BlockManager extends DefaultPluginManager implements EventSubscriberInterface {
 
   /**
    * An array of all available modules and their data.
@@ -121,4 +124,22 @@ public function getCategories() {
     return $categories;
   }
 
+  /**
+   * {@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/Plugin/views/display/Block.php b/core/modules/block/lib/Drupal/block/Plugin/views/display/Block.php
index 657b635..35f32cf 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, array $plugin_definition) {
+    return new static(
+      $configuration,
+      $plugin_id,
+      $plugin_definition,
+      $container->get('event_dispatcher')
+    );
+  }
+
   protected function defineOptions() {
     $options = parent::defineOptions();
 
@@ -363,15 +402,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/menu.module b/core/modules/menu/menu.module
index 660e1df..7b3a51f 100644
--- a/core/modules/menu/menu.module
+++ b/core/modules/menu/menu.module
@@ -11,10 +11,12 @@
  * 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\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\MenuLinkStorageController;
@@ -196,9 +198,11 @@ function menu_menu_predelete(Menu $menu) {
 function menu_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);
   }
 }
 
