diff --git a/core/modules/field/lib/Drupal/field/Entity/Field.php b/core/modules/field/lib/Drupal/field/Entity/Field.php
index 3421461..8308e28 100644
--- a/core/modules/field/lib/Drupal/field/Entity/Field.php
+++ b/core/modules/field/lib/Drupal/field/Entity/Field.php
@@ -12,6 +12,7 @@
 use Drupal\Core\Annotation\Translation;
 use Drupal\Core\Config\Entity\ConfigEntityBase;
 use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\EntityStorageControllerInterface;
 use Drupal\field\FieldException;
 use Drupal\field\FieldInterface;
 
@@ -272,42 +273,35 @@ public function getExportProperties() {
   }
 
   /**
-   * Overrides \Drupal\Core\Entity\Entity::save().
-   *
-   * @return int
-   *   Either SAVED_NEW or SAVED_UPDATED, depending on the operation performed.
+   * Overrides \Drupal\Core\Entity\Entity::preSave().
    *
    * @throws \Drupal\field\FieldException
    *   If the field definition is invalid.
    * @throws \Drupal\Core\Entity\EntityStorageException
    *   In case of failures at the configuration storage level.
    */
-  public function save() {
+  public function preSave(EntityStorageControllerInterface $storage_controller) {
     // Clear the derived data about the field.
     unset($this->schema);
 
     if ($this->isNew()) {
-      return $this->saveNew();
+      return $this->preSaveNew($storage_controller);
     }
     else {
-      return $this->saveUpdated();
+      return $this->preSaveUpdated($storage_controller);
     }
   }
 
   /**
-   * Saves a new field definition.
+   * Prepares saving a new field definition.
    *
-   * @return int
-   *   SAVED_NEW if the definition was saved.
+   * @param \Drupal\Core\Entity\EntityStorageControllerInterface $storage_controller
+   *   The entity storage controller.
    *
-   * @throws \Drupal\field\FieldException
-   *   If the field definition is invalid.
-   * @throws \Drupal\Core\Entity\EntityStorageException
-   *   In case of failures at the configuration storage level.
+   * @throws \Drupal\field\FieldException If the field definition is invalid.
    */
-  protected function saveNew() {
+   protected function preSaveNew(EntityStorageControllerInterface $storage_controller) {
     $entity_manager = \Drupal::entityManager();
-    $storage_controller = $entity_manager->getStorageController($this->entityType);
 
     // Assign the ID.
     $this->id = $this->id();
@@ -325,6 +319,7 @@ protected function saveNew() {
     }
 
     // Ensure the field name is unique (we do not care about deleted fields).
+    // @todo Remove ?
     if ($prior_field = $storage_controller->load($this->id)) {
       $message = $prior_field->active ?
         'Attempt to create field name %name which already exists and is active.' :
@@ -355,100 +350,99 @@ protected function saveNew() {
 
     // Notify the entity storage controller.
     $entity_manager->getStorageController($this->entity_type)->onFieldCreate($this);
-
-    // Save the configuration.
-    $result = parent::save();
-    field_cache_clear();
-
-    return $result;
   }
 
   /**
-   * Saves an updated field definition.
-   *
-   * @return int
-   *   SAVED_UPDATED if the definition was saved.
+   * Prepares saving an updated field definition.
    *
-   * @throws \Drupal\field\FieldException
-   *   If the field definition is invalid.
-   * @throws \Drupal\Core\Entity\EntityStorageException
-   *   In case of failures at the configuration storage level.
+   * @param \Drupal\Core\Entity\EntityStorageControllerInterface $storage_controller
+   *   The entity storage controller.
    */
-  protected function saveUpdated() {
+  protected function preSaveUpdated(EntityStorageControllerInterface $storage_controller) {
     $module_handler = \Drupal::moduleHandler();
     $entity_manager = \Drupal::entityManager();
-    $storage_controller = $entity_manager->getStorageController($this->entityType);
-
-    $original = $storage_controller->loadUnchanged($this->id());
-    $this->original = $original;
 
     // Some updates are always disallowed.
-    if ($this->type != $original->type) {
+    if ($this->type != $this->original->type) {
       throw new FieldException("Cannot change an existing field's type.");
     }
-    if ($this->entity_type != $original->entity_type) {
+    if ($this->entity_type != $this->original->entity_type) {
       throw new FieldException("Cannot change an existing field's entity_type.");
     }
 
-    // Make sure all settings are present, so that a complete field definition
-    // is saved. This allows calling code to perform partial updates on field
-    // objects.
-    $this->settings += $original->settings;
+    // Make sure all settings are present, so that a complete field
+    // definition is passed to the various hooks and written to config.
+    $this->settings += \Drupal::service('plugin.manager.entity.field.field_type')->getDefaultSettings($this->type);
 
     // See if any module forbids the update by throwing an exception. This
     // invokes hook_field_update_forbid().
-    $module_handler->invokeAll('field_update_forbid', array($this, $original));
+    $module_handler->invokeAll('field_update_forbid', array($this, $this->original));
 
     // Notify the storage controller. The controller can reject the definition
     // update as invalid by raising an exception, which stops execution before
     // the definition is written to config.
-    $entity_manager->getStorageController($this->entity_type)->onFieldUpdate($this, $original);
+    $entity_manager->getStorageController($this->entity_type)->onFieldUpdate($this);
+  }
 
-    // Save the configuration.
-    $result = parent::save();
+  /**
+   * {@inheritdoc}
+   */
+  public function postSave(EntityStorageControllerInterface $storage_controller, $update = TRUE) {
+    // Clear the cache.
     field_cache_clear();
-
-    return $result;
   }
 
   /**
    * {@inheritdoc}
    */
-  public function delete() {
-    if (!$this->deleted) {
-      $instance_controller = \Drupal::entityManager()->getStorageController('field_instance');
-      $state = \Drupal::state();
-
-      // Delete all non-deleted instances.
-      $instance_ids = array();
-      foreach ($this->getBundles() as $bundle) {
-        $instance_ids[] = "{$this->entity_type}.$bundle.{$this->name}";
+  public static function preDelete(EntityStorageControllerInterface $storage_controller, array $fields) {
+    $state = \Drupal::state();
+
+    // Keep the field definitions in the state storage so we can use them later
+    // during field_purge_batch().
+    $deleted_fields = $state->get('field.field.deleted') ?: array();
+    foreach ($fields as $field) {
+      if (!$field->deleted) {
+        $config = $field->getExportProperties();
+        $config['deleted'] = TRUE;
+        $deleted_fields[$field->uuid] = $config;
+        $deleted_fields[$field->uuid]['bundles'] = $field->getBundles();
+
+        // Notify the storage.
+        \Drupal::entityManager()->getStorageController($field->entity_type)->onFieldDelete($field);
       }
-      foreach ($instance_controller->loadMultiple($instance_ids) as $instance) {
-        // By default, FieldInstance::delete() will automatically try to delete
-        // a field definition when it is deleting the last instance of the
-        // field. Since the whole field is being deleted here, pass FALSE as
-        // the $field_cleanup parameter to prevent a loop.
-        $instance->delete(FALSE);
-      }
-
-      \Drupal::entityManager()->getStorageController($this->entity_type)->onFieldDelete($this);
-
-      // Delete the configuration of this field and save the field configuration
-      // in the key_value table so we can use it later during
-      // field_purge_batch(). This makes sure a new field can be created
-      // immediately with the same name.
-      $deleted_fields = $state->get('field.field.deleted') ?: array();
-      $config = $this->getExportProperties();
-      $config['deleted'] = TRUE;
-      $deleted_fields[$this->uuid] = $config;
-      $state->set('field.field.deleted', $deleted_fields);
-
-      parent::delete();
+    }
+    $state->set('field.field.deleted', $deleted_fields);
+  }
 
-      // Clear the cache.
-      field_cache_clear();
+  /**
+   * {@inheritdoc}
+   */
+  public static function postDelete(EntityStorageControllerInterface $storage_controller, array $fields) {
+    $instance_controller = \Drupal::entityManager()->getStorageController('field_instance');
+    $state = \Drupal::state();
+    $deleted_fields = $state->get('field.field.deleted') ?: array();
+    foreach ($fields as $field) {
+      if (!$field->deleted) {
+        // Delete all non-deleted instances.
+        $instance_ids = array();
+        foreach ($deleted_fields[$field->uuid]['bundles'] as $entity_type => $bundles) {
+          foreach ($bundles as $bundle) {
+            $instance_ids[] = "$entity_type.$bundle.$field->id";
+          }
+        }
+        foreach ($instance_controller->loadMultiple($instance_ids) as $instance) {
+          // By default, FieldInstance::delete() will automatically try to delete
+          // a field definition when it is deleting the last instance of the
+          // field. Since the whole field is being deleted here, pass FALSE as
+          // the $field_cleanup parameter to prevent a loop.
+          $instance->delete();
+        }
+      }
     }
+
+    // Clear the cache.
+    field_cache_clear();
   }
 
   /**
diff --git a/core/modules/field/lib/Drupal/field/Entity/FieldInstance.php b/core/modules/field/lib/Drupal/field/Entity/FieldInstance.php
index eaa0c70..9d5eb5b 100644
--- a/core/modules/field/lib/Drupal/field/Entity/FieldInstance.php
+++ b/core/modules/field/lib/Drupal/field/Entity/FieldInstance.php
@@ -12,6 +12,7 @@
 use Drupal\Core\Annotation\Translation;
 use Drupal\Core\Config\Entity\ConfigEntityBase;
 use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\EntityStorageControllerInterface;
 use Drupal\field\FieldException;
 use Drupal\field\FieldInstanceInterface;
 
@@ -323,160 +324,107 @@ public function getExportProperties() {
   }
 
   /**
-   * Overrides \Drupal\Core\Entity\Entity::save().
-   *
-   * @return
-   *   Either SAVED_NEW or SAVED_UPDATED, depending on the operation performed.
+   * Overrides \Drupal\Core\Entity\Entity::preSave().
    *
    * @throws \Drupal\field\FieldException
    *   If the field instance definition is invalid.
-   *
    * @throws \Drupal\Core\Entity\EntityStorageException
    *   In case of failures at the configuration storage level.
    */
-  public function save() {
+  public function preSave(EntityStorageControllerInterface $storage_controller) {
+    $entity_manager = \Drupal::entityManager();
+
     if ($this->isNew()) {
-      return $this->saveNew();
+      // Ensure the field instance is unique within the bundle.
+      // @todo remove ?
+      if ($prior_instance = $storage_controller->load($this->id())) {
+        throw new FieldException(format_string('Attempt to create an instance of field %name on bundle @bundle that already has an instance of that field.', array('%name' => $this->field->name, '@bundle' => $this->bundle)));
+      }
+      // Set the field UUID.
+      $this->field_uuid = $this->field->uuid;
+      // Set the default instance settings.
+      $this->settings += \Drupal::service('plugin.manager.entity.field.field_type')->getDefaultInstanceSettings($this->field->type);
+      // Notify the entity storage controller.
+      $entity_manager->getStorageController($this->entity_type)->onInstanceCreate($this);
     }
     else {
-      return $this->saveUpdated();
+      // Some updates are always disallowed.
+      if ($this->entity_type != $this->original->entity_type) {
+        throw new FieldException("Cannot change an existing instance's entity_type.");
+      }
+      if ($this->bundle != $this->original->bundle && empty($this->bundle_rename_allowed)) {
+        throw new FieldException("Cannot change an existing instance's bundle.");
+      }
+      if ($this->field_uuid != $this->original->field_uuid) {
+        throw new FieldException("Cannot change an existing instance's field.");
+      }
+      // Set the default instance settings.
+      $this->settings += \Drupal::service('plugin.manager.entity.field.field_type')->getDefaultInstanceSettings($this->field->type);
+      // Notify the entity storage controller.
+      $entity_manager->getStorageController($this->entity_type)->onInstanceUpdate($this);
     }
   }
 
   /**
-   * Saves a new field instance definition.
-   *
-   * @return
-   *   SAVED_NEW if the definition was saved.
-   *
-   * @throws \Drupal\field\FieldException
-   *   If the field instance definition is invalid.
-   *
-   * @throws \Drupal\Core\Entity\EntityStorageException
-   *   In case of failures at the configuration storage level.
+   * {@inheritdoc}
    */
-  protected function saveNew() {
-    $instance_controller = \Drupal::entityManager()->getStorageController($this->entityType);
-
-    // Ensure the field instance is unique within the bundle.
-    if ($prior_instance = $instance_controller->load($this->id())) {
-      throw new FieldException(format_string('Attempt to create an instance of field %name on bundle @bundle that already has an instance of that field.', array('%name' => $this->field->name, '@bundle' => $this->bundle)));
-    }
-
-    // Set the field UUID.
-    $this->field_uuid = $this->field->uuid;
-
-    // Ensure default values are present.
-    $this->prepareSave();
-
-    // Save the configuration.
-    $result = parent::save();
+  public function postSave(EntityStorageControllerInterface $storage_controller, $update = TRUE) {
+    // Clear the cache.
     field_cache_clear();
-
-    return $result;
   }
 
   /**
-   * Saves an updated field instance definition.
-   *
-   * @return
-   *   SAVED_UPDATED if the definition was saved.
-   *
-   * @throws \Drupal\field\FieldException
-   *   If the field instance definition is invalid.
-   *
-   * @throws \Drupal\Core\Entity\EntityStorageException
-   *   In case of failures at the configuration storage level.
+   * {@inheritdoc}
    */
-  protected function saveUpdated() {
-    $instance_controller = \Drupal::entityManager()->getStorageController($this->entityType);
+  public static function preDelete(EntityStorageControllerInterface $storage_controller, array $instances) {
+    $state = \Drupal::state();
 
-    $original = $instance_controller->loadUnchanged($this->getOriginalID());
-    $this->original = $original;
+    // Keep the instance definitions in the state storage so we can use them
+    // later during field_purge_batch().
+    $deleted_instances = $state->get('field.instance.deleted') ?: array();
+    foreach ($instances as $instance) {
+      if (!$instance->deleted) {
+        $config = $instance->getExportProperties();
+        $config['deleted'] = TRUE;
+        $deleted_instances[$instance->uuid] = $config;
 
-    // Some updates are always disallowed.
-    if ($this->entity_type != $original->entity_type) {
-      throw new FieldException("Cannot change an existing instance's entity_type.");
-    }
-    if ($this->bundle != $original->bundle && empty($this->bundle_rename_allowed)) {
-      throw new FieldException("Cannot change an existing instance's bundle.");
-    }
-    if ($this->field_uuid != $original->field_uuid) {
-      throw new FieldException("Cannot change an existing instance's field.");
+        // Notify the entity storage controller.
+        \Drupal::entityManager()->getStorageController($instance->entity_type)->onInstanceDelete($instance);
+      }
     }
-
-    // Ensure default values are present.
-    $this->prepareSave();
-
-    // Notify the entity storage controller.
-    \Drupal::entityManager()->getStorageController($this->entity_type)->onInstanceUpdate($this);
-
-    // Save the configuration.
-    $result = parent::save();
-    field_cache_clear();
-
-    return $result;
+    $state->set('field.instance.deleted', $deleted_instances);
   }
 
   /**
-   * Prepares the instance definition for saving.
-   */
-  protected function prepareSave() {
-    $field_type_info = \Drupal::service('plugin.manager.entity.field.field_type')->getDefinition($this->field->type);
-
-    // Set the default instance settings.
-    $this->settings += $field_type_info['instance_settings'];
-  }
-
-  /**
-   * Overrides \Drupal\Core\Entity\Entity::delete().
-   *
-   * @param bool $field_cleanup
-   *   (optional) If TRUE, the field will be deleted as well if its last
-   *   instance is being deleted. If FALSE, it is the caller's responsibility to
-   *   handle the case of fields left without instances. Defaults to TRUE.
+   * {@inheritdoc}
    */
-  public function delete($field_cleanup = TRUE) {
-    if (!$this->deleted) {
-      $state = \Drupal::state();
-
-      // Delete the configuration of this instance and save the configuration
-      // in the key_value table so we can use it later during
-      // field_purge_batch().
-      $deleted_instances = $state->get('field.instance.deleted') ?: array();
-      $config = $this->getExportProperties();
-      $config['deleted'] = TRUE;
-      $deleted_instances[$this->uuid] = $config;
-      $state->set('field.instance.deleted', $deleted_instances);
-
-      parent::delete();
-
-      // Notify the entity storage controller.
-      \Drupal::entityManager()->getStorageController($this->entity_type)->onInstanceDelete($this);
-
-      // Clear the cache.
-      field_cache_clear();
-
-      // Remove the instance from the entity form displays.
-      if ($form_display = entity_load('entity_form_display', $this->entity_type . '.' . $this->bundle . '.default')) {
-        $form_display->removeComponent($this->field->name)->save();
-      }
-
-      // Remove the instance from the entity displays.
-      $ids = array();
-      $view_modes = array('default' => array()) + entity_get_view_modes($this->entity_type);
-      foreach (array_keys($view_modes) as $view_mode) {
-        $ids[] = $this->entity_type . '.' . $this->bundle . '.' . $view_mode;
-      }
-      foreach (entity_load_multiple('entity_display', $ids) as $display) {
-        $display->removeComponent($this->field->name)->save();
-      }
-
-      // Delete the field itself if we just deleted its last instance.
-      if ($field_cleanup && count($this->field->getBundles()) == 0) {
-        $this->field->delete();
+  public static function postDelete(EntityStorageControllerInterface $storage_controller, array $instances) {
+    foreach ($instances as $instance) {
+      if (!$instance->deleted) {
+        // Remove the instance from the entity form displays.
+        if ($form_display = entity_load('entity_form_display', $instance->entity_type . '.' . $instance->bundle . '.default')) {
+          $form_display->removeComponent($instance->field->id)->save();
+        }
+
+        // Remove the instance from the entity displays.
+        $ids = array();
+        $view_modes = array('default' => array()) + entity_get_view_modes($instance->entity_type);
+        foreach (array_keys($view_modes) as $view_mode) {
+          $ids[] = $instance->entity_type . '.' . $instance->bundle . '.' . $view_mode;
+        }
+        foreach (entity_load_multiple('entity_display', $ids) as $display) {
+          $display->removeComponent($instance->field->id)->save();
+        }
+
+        // Delete the field if it doesn't have more instances associated to it.
+        if (count($instance->field->getBundles()) == 0) {
+          $instance->field->delete();
+        }
       }
     }
+
+    // Clear the cache.
+    field_cache_clear();
   }
 
   /**
