diff --git a/core/config/schema/core.data_types.schema.yml b/core/config/schema/core.data_types.schema.yml
index ab6b9440652475eb206b405d18d5acaaa9f3f9f2..763d0966da8a9006c8ae687f4f42953a55edae8a 100644
--- a/core/config/schema/core.data_types.schema.yml
+++ b/core/config/schema/core.data_types.schema.yml
@@ -355,9 +355,6 @@ base_entity_reference_field_settings:
     target_type:
       type: string
       label: 'Type of item to reference'
-    target_bundle:
-      type: string
-      label: 'Bundle of item to reference'
 
 field_config_base:
   type: config_entity
diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EntityReferenceItem.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EntityReferenceItem.php
index 18c050646f361ba84d70c3d05b2a306073e6cfd4..70397fa1e64523e748ce27b9ea8dc04a03f64f20 100644
--- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EntityReferenceItem.php
+++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EntityReferenceItem.php
@@ -45,7 +45,6 @@ class EntityReferenceItem extends FieldItemBase {
   public static function defaultStorageSettings() {
     return array(
       'target_type' => \Drupal::moduleHandler()->moduleExists('node') ? 'node' : 'user',
-      'target_bundle' => NULL,
     ) + parent::defaultStorageSettings();
   }
 
@@ -93,16 +92,11 @@ public static function propertyDefinitions(FieldStorageDefinitionInterface $fiel
       ->setComputed(TRUE)
       ->setReadOnly(FALSE)
       ->setTargetDefinition(EntityDataDefinition::create($settings['target_type']))
+      // We can add a constraint for the target entity type. The list of
+      // referenceable bundles is a field setting, so the corresponding
+      // constraint is added dynamically in ::getConstraints().
       ->addConstraint('EntityType', $settings['target_type']);
 
-    if (isset($settings['target_bundle'])) {
-      $properties['entity']->addConstraint('Bundle', $settings['target_bundle']);
-      // Set any further bundle constraints on the target definition as well,
-      // such that it can derive more special data types if possible. For
-      // example, "entity:node:page" instead of "entity:node".
-      $properties['entity']->getTargetDefinition()
-        ->addConstraint('Bundle', $settings['target_bundle']);
-    }
     return $properties;
   }
 
@@ -151,6 +145,28 @@ public static function schema(FieldStorageDefinitionInterface $field_definition)
     return $schema;
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function getConstraints() {
+    $constraints = parent::getConstraints();
+    list($current_handler) = explode(':', $this->getSetting('handler'), 2);
+    if ($current_handler === 'default') {
+      $handler_settings = $this->getSetting('handler_settings');
+      if (!empty($handler_settings['target_bundles'])) {
+        $constraint_manager = \Drupal::typedDataManager()->getValidationConstraintManager();
+        $constraints[] = $constraint_manager->create('ComplexData', [
+          'entity' => [
+            'Bundle' => [
+              'bundle' => $handler_settings['target_bundles'],
+            ],
+          ],
+        ]);
+      }
+    }
+    return $constraints;
+  }
+
   /**
    * {@inheritdoc}
    */
diff --git a/core/modules/entity_reference/src/ConfigurableEntityReferenceItem.php b/core/modules/entity_reference/src/ConfigurableEntityReferenceItem.php
index 376fef859100e7a546d48b63ece8e98f13633a54..332de7b80238aa878f9cb122aa624f0cd9850c4a 100644
--- a/core/modules/entity_reference/src/ConfigurableEntityReferenceItem.php
+++ b/core/modules/entity_reference/src/ConfigurableEntityReferenceItem.php
@@ -30,17 +30,6 @@
  */
 class ConfigurableEntityReferenceItem extends EntityReferenceItem implements OptionsProviderInterface, PreconfiguredFieldUiOptionsInterface {
 
-  /**
-   * {@inheritdoc}
-   */
-  public static function defaultStorageSettings() {
-    $settings = parent::defaultStorageSettings();
-    // The target bundle is handled by the 'target_bundles' property in the
-    // 'handler_settings' instance setting.
-    unset($settings['target_bundle']);
-    return $settings;
-  }
-
   /**
    * {@inheritdoc}
    */
diff --git a/core/modules/field/field.install b/core/modules/field/field.install
new file mode 100644
index 0000000000000000000000000000000000000000..f381b05548b1080bcc33ef83868b538648e696d8
--- /dev/null
+++ b/core/modules/field/field.install
@@ -0,0 +1,28 @@
+<?php
+
+/**
+ * @file
+ * Install, update and uninstall functions for the field module.
+ */
+
+/**
+ * Removes the stale 'target_bundle' storage setting on entity_reference fields.
+ */
+function field_update_8001() {
+  $config = \Drupal::configFactory();
+  /** @var \Drupal\Core\Field\FieldTypePluginManager $field_type_manager */
+  $field_type_manager = \Drupal::service('plugin.manager.field.field_type');
+  $item_class = 'Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem';
+
+  // Iterate on all fields storage.
+  foreach ($config->listAll('field.storage.') as $field_id) {
+    $field_storage = $config->getEditable($field_id);
+    $class = $field_type_manager->getPluginClass($field_storage->get('type'));
+
+    // Deal only with entity reference fields and descendants.
+    if ($class == $item_class || is_subclass_of($class, $item_class)) {
+      // Remove 'target_bundle' from settings.
+      $field_storage->clear('settings.target_bundle')->save(TRUE);
+    }
+  }
+}
diff --git a/core/modules/field/src/Tests/Migrate/d6/MigrateFieldInstanceTest.php b/core/modules/field/src/Tests/Migrate/d6/MigrateFieldInstanceTest.php
index c0fb2f5344c0ef47f5aad4d220e497f8d9d652d1..19f835f56faa41733fd01c2dc3af75b53263885b 100644
--- a/core/modules/field/src/Tests/Migrate/d6/MigrateFieldInstanceTest.php
+++ b/core/modules/field/src/Tests/Migrate/d6/MigrateFieldInstanceTest.php
@@ -83,7 +83,6 @@ public function testFieldInstanceSettings() {
       // storages so we end up with the default value for this setting.
       'handler' => 'default:node',
       'handler_settings' => array(),
-      'target_bundle' => NULL,
     );
     $field_settings = $field->getSettings();
     ksort($expected);
diff --git a/core/modules/field/src/Tests/Update/EntityReferenceTargetBundleUpdateTest.php b/core/modules/field/src/Tests/Update/EntityReferenceTargetBundleUpdateTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..07b2d74fe043883f1bc2b31c5797801782285eea
--- /dev/null
+++ b/core/modules/field/src/Tests/Update/EntityReferenceTargetBundleUpdateTest.php
@@ -0,0 +1,53 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\field\Tests\Update\EntityReferenceTargetBundleUpdateTest.
+ */
+
+namespace Drupal\field\Tests\Update;
+
+use Drupal\system\Tests\Update\UpdatePathTestBase;
+
+/**
+ * Tests that field settings are properly updated during database updates.
+ *
+ * @group field
+ */
+class EntityReferenceTargetBundleUpdateTest extends UpdatePathTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setDatabaseDumpFiles() {
+    $this->databaseDumpFiles = [
+      __DIR__ . '/../../../../system/tests/fixtures/update/drupal-8.bare.standard.php.gz',
+    ];
+  }
+
+  /**
+   * Tests field_update_8001().
+   *
+   * @see field_update_8001()
+   */
+  public function testFieldUpdate8001() {
+    $configFactory = $this->container->get('config.factory');
+
+    // Load the 'node.field_image' field storage config, and check that is has
+    // a 'target_bundle' setting.
+    /** @var \Drupal\Core\Config\Config */
+    $config = $configFactory->get('field.storage.node.field_image');
+    $settings = $config->get('settings');
+    $this->assertTrue(array_key_exists('target_bundle', $settings));
+
+    // Run updates.
+    $this->runUpdates();
+
+    // Reload the config, and check that the 'target_bundle' setting has been
+    // removed.
+    $config = $configFactory->get('field.storage.node.field_image');
+    $settings = $config->get('settings');
+    $this->assertFalse(array_key_exists('target_bundle', $settings));
+  }
+
+}
diff --git a/core/modules/system/src/Tests/Entity/EntityFieldTest.php b/core/modules/system/src/Tests/Entity/EntityFieldTest.php
index 5d93c7862df7c7809f7607261b13a1d3fdf236be..6fae79b31dd3a25bb78cd1efc7e4b354d96f816b 100644
--- a/core/modules/system/src/Tests/Entity/EntityFieldTest.php
+++ b/core/modules/system/src/Tests/Entity/EntityFieldTest.php
@@ -689,9 +689,9 @@ public function testEntityConstraintValidation() {
     $definition = BaseFieldDefinition::create('entity_reference')
       ->setLabel('Test entity')
       ->setSetting('target_type', 'node')
-      ->setSetting('target_bundle', 'article');
+      ->setSetting('handler_settings', ['target_bundles' => ['article' => 'article']]);
     $reference_field = \Drupal::TypedDataManager()->create($definition);
-    $reference = $reference_field->appendItem(array('entity' => $node))->get('entity');
+    $reference = $reference_field->appendItem(array('entity' => $node));
     $violations = $reference->validate();
     $this->assertEqual($violations->count(), 1);
 
diff --git a/core/profiles/standard/config/install/field.storage.node.field_image.yml b/core/profiles/standard/config/install/field.storage.node.field_image.yml
index 9c1a644890aa4ad8ecc049ba8f29b84bb8e6b0db..ad719e4e6acf38d5f18fee5e57a48d48c380f4ff 100644
--- a/core/profiles/standard/config/install/field.storage.node.field_image.yml
+++ b/core/profiles/standard/config/install/field.storage.node.field_image.yml
@@ -19,7 +19,6 @@ settings:
   target_type: file
   display_field: false
   display_default: false
-  target_bundle: null
 module: image
 locked: false
 cardinality: 1
diff --git a/core/profiles/standard/config/install/field.storage.user.user_picture.yml b/core/profiles/standard/config/install/field.storage.user.user_picture.yml
index 48da5578a52a6a439dc4471ad8da39455f204fdf..d81db8bb9b4be81dda425f525f544c77b17e2016 100644
--- a/core/profiles/standard/config/install/field.storage.user.user_picture.yml
+++ b/core/profiles/standard/config/install/field.storage.user.user_picture.yml
@@ -19,7 +19,6 @@ settings:
   target_type: file
   display_field: false
   display_default: false
-  target_bundle: null
 module: image
 locked: false
 cardinality: 1