diff --git a/core/lib/Drupal/Core/Config/ConfigImporter.php b/core/lib/Drupal/Core/Config/ConfigImporter.php
index 5e11697..f644ddd 100644
--- a/core/lib/Drupal/Core/Config/ConfigImporter.php
+++ b/core/lib/Drupal/Core/Config/ConfigImporter.php
@@ -254,12 +254,60 @@ public function validate() {
    *   The name of the configuration to process.
    */
   protected function process($op, $name) {
-    if (!$this->importInvokeOwner($op, $name)) {
-      $this->importConfig($op, $name);
+    if ($this->checkOp($op, $name)) {
+      if ($entity_type = $this->configManager->getEntityTypeIdByName($name)) {
+        $this->importConfigurationEntity($op, $name, $entity_type);
+      }
+      else {
+        $this->importConfig($op, $name);
+      }
     }
   }
 
   /**
+   * Checks that the operation is still valid.
+   *
+   * During a configuration import secondary writes and deletes are possible.
+   * This method checks that the operation is still valid before processing a
+   * configuration change.
+   *
+   * @param string $op
+   *   The change operation.
+   * @param $name
+   *   The name of the configuration to process.
+   *
+   * @return bool
+   *   TRUE is to continue processing, FALSE otherwise.
+   */
+  protected function checkOp($op, $name) {
+    $target_exists = $this->storageComparer->getTargetStorage()->exists($name);
+    switch ($op) {
+      case 'delete':
+        if (!$target_exists) {
+          // The configuration has already been deleted. For example, a field
+          // is automatically deleted if all the instances are.
+          $this->setProcessed($op, $name);
+          return FALSE;
+        }
+        break;
+      case 'create':
+        if ($target_exists) {
+          // Become an update. This is possible since updates are run after
+          // creates.
+          $this->storageComparer->swapOp('create', 'update', $name);
+          return FALSE;
+        }
+        break;
+      case 'update':
+        if (!$target_exists) {
+          // Error?
+        }
+        break;
+    }
+    return TRUE;
+  }
+
+  /**
    * Writes a configuration change from the source to the target storage.
    *
    * @param string $op
@@ -293,6 +341,8 @@ protected function importConfig($op, $name) {
    *   create or update.
    * @param string $name
    *   The name of the configuration to process.
+   * @param string $entity_type
+   *   The entity type of the configuration to process.
    *
    * @throws \Drupal\Core\Entity\EntityStorageException
    *   Thrown if the data is owned by an entity type, but the entity storage
@@ -328,7 +378,25 @@ protected function importInvokeOwner($op, $name) {
       $this->setProcessed($op, $name);
       return TRUE;
     }
-    return FALSE;
+  }
+
+  protected function importConfigurationEntity($op, $name, $entity_type) {
+    $old_config = new Config($name, $this->storageComparer->getTargetStorage(), $this->eventDispatcher, $this->typedConfigManager);
+    if ($old_data = $this->storageComparer->getTargetStorage()->read($name)) {
+      $old_config->initWithData($old_data);
+    }
+
+    $data = $this->storageComparer->getSourceStorage()->read($name);
+    $new_config = new Config($name, $this->storageComparer->getTargetStorage(), $this->eventDispatcher, $this->typedConfigManager);
+    if ($data !== FALSE) {
+      $new_config->setData($data);
+    }
+
+    $method = 'import' . ucfirst($op);
+    // Call the configuration entity's storage controller to handle the
+    // configuration change.
+    $this->configManager->getEntityManager()->getStorageController($entity_type)->$method($name, $new_config, $old_config);
+    $this->setProcessed($op, $name);
   }
 
   /**
diff --git a/core/lib/Drupal/Core/Config/StorageComparer.php b/core/lib/Drupal/Core/Config/StorageComparer.php
index ac89537..6170856 100644
--- a/core/lib/Drupal/Core/Config/StorageComparer.php
+++ b/core/lib/Drupal/Core/Config/StorageComparer.php
@@ -234,4 +234,12 @@ protected function getAndSortConfigData() {
     $this->sourceNames = $dependency_manager->setData($this->sourceData)->sortAll();
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function swapOp($from, $to, $name) {
+    $key = array_search($name, $this->changelist[$from]);
+    unset($this->changelist[$from][$key]);
+    $this->addChangeList($to, array($name));
+  }
 }
diff --git a/core/lib/Drupal/Core/Config/StorageComparerInterface.php b/core/lib/Drupal/Core/Config/StorageComparerInterface.php
index 3c6c666..bc27635 100644
--- a/core/lib/Drupal/Core/Config/StorageComparerInterface.php
+++ b/core/lib/Drupal/Core/Config/StorageComparerInterface.php
@@ -80,4 +80,18 @@ public function hasChanges($ops = array('delete', 'create', 'update'));
    */
   public function validateSiteUuid();
 
+  /**
+   * Moves a configuration name from one change list to another.
+   *
+   * @param string $name
+   *   The configuration object name.
+   * @param string $from
+   *   The current change operation. Either delete, create or update.
+   * @param string $to
+   *   The change operation to change to. Either delete, create or update.
+   *
+   * @return $this
+   */
+  public function swapOp($name, $from, $to);
+
 }
diff --git a/core/modules/block/custom_block/lib/Drupal/custom_block/Entity/CustomBlockType.php b/core/modules/block/custom_block/lib/Drupal/custom_block/Entity/CustomBlockType.php
index e8eee2e..de4a109 100644
--- a/core/modules/block/custom_block/lib/Drupal/custom_block/Entity/CustomBlockType.php
+++ b/core/modules/block/custom_block/lib/Drupal/custom_block/Entity/CustomBlockType.php
@@ -75,7 +75,7 @@ class CustomBlockType extends ConfigEntityBase implements CustomBlockTypeInterfa
   public function postSave(EntityStorageInterface $storage, $update = TRUE) {
     parent::postSave($storage, $update);
 
-    if (!$update) {
+    if (!$update && !$this->isSyncing()) {
       entity_invoke_bundle_hook('create', 'custom_block', $this->id());
       if (!$this->isSyncing()) {
         custom_block_add_body_field($this->id);
diff --git a/core/modules/entity_reference/entity_reference.module b/core/modules/entity_reference/entity_reference.module
index 75d9dfd..88acbcb 100644
--- a/core/modules/entity_reference/entity_reference.module
+++ b/core/modules/entity_reference/entity_reference.module
@@ -71,6 +71,11 @@ function entity_reference_field_config_update(FieldConfigInterface $field) {
     return;
   }
 
+  if ($field->isSyncing()) {
+    // Don't change anything during a configuration sync.
+    return;
+  }
+
   if ($field->getSetting('target_type') == $field->original->getSetting('target_type')) {
     // Target type didn't change.
     return;
diff --git a/core/modules/field/lib/Drupal/field/Tests/FieldImportDeleteTest.php b/core/modules/field/lib/Drupal/field/Tests/FieldImportDeleteTest.php
index d2388f7..59fc321 100644
--- a/core/modules/field/lib/Drupal/field/Tests/FieldImportDeleteTest.php
+++ b/core/modules/field/lib/Drupal/field/Tests/FieldImportDeleteTest.php
@@ -6,6 +6,7 @@
  */
 
 namespace Drupal\field\Tests;
+use Drupal\Component\Utility\String;
 
 /**
  * Tests deleting fields and instances as part of config import.
@@ -31,13 +32,21 @@ public static function getInfo() {
    * Tests deleting fields and instances as part of config import.
    */
   public function testImportDelete() {
+    // At this point there are 5 field configuration objects in the active
+    // storage.
+    // - field.field.entity_test.field_test_import
+    // - field.field.entity_test.field_test_import_2
+    // - field.instance.entity_test.entity_test.field_test_import
+    // - field.instance.entity_test.entity_test.field_test_import_2
+    // - field.instance.entity_test.test_bundle.field_test_import_2
+
     $field_name = 'field_test_import';
     $field_id = "entity_test.$field_name";
     $field_name_2 = 'field_test_import_2';
     $field_id_2 = "entity_test.$field_name_2";
-    $instance_id = "entity_test.test_bundle.$field_name";
-    $instance_id_2a = "entity_test.test_bundle.$field_name_2";
-    $instance_id_2b = "entity_test.test_bundle_2.$field_name_2";
+    $instance_id = "entity_test.entity_test.$field_name";
+    $instance_id_2a = "entity_test.entity_test.$field_name_2";
+    $instance_id_2b = "entity_test.test_bundle.$field_name_2";
     $field_config_name = "field.field.$field_id";
     $field_config_name_2 = "field.field.$field_id_2";
     $instance_config_name = "field.instance.$instance_id";
@@ -45,7 +54,7 @@ public function testImportDelete() {
     $instance_config_name_2b = "field.instance.$instance_id_2b";
 
     // Create a second bundle for the 'Entity test' entity type.
-    entity_test_create_bundle('test_bundle_2');
+    entity_test_create_bundle('test_bundle');
 
     // Import default config.
     $this->installConfig(array('field_test_config'));
@@ -57,11 +66,14 @@ public function testImportDelete() {
     $active = $this->container->get('config.storage');
     $staging = $this->container->get('config.storage.staging');
     $this->copyConfig($active, $staging);
-    $staging->delete($field_config_name);
-    $staging->delete($field_config_name_2);
-    $staging->delete($instance_config_name);
-    $staging->delete($instance_config_name_2a);
-    $staging->delete($instance_config_name_2b);
+    $this->assertTrue($staging->delete($field_config_name), String::format('Deleted field: !field', array('!field' => $field_config_name)));
+    $this->assertTrue($staging->delete($field_config_name_2), String::format('Deleted field: !field', array('!field' => $field_config_name_2)));
+    $this->assertTrue($staging->delete($instance_config_name), String::format('Deleted field instance: !field_instance', array('!field_instance' => $instance_config_name)));
+    $this->assertTrue($staging->delete($instance_config_name_2a), String::format('Deleted field instance: !field_instance', array('!field_instance' => $instance_config_name_2a)));
+    $this->assertTrue($staging->delete($instance_config_name_2b), String::format('Deleted field instance: !field_instance', array('!field_instance' => $instance_config_name_2b)));
+
+    $deletes = $this->configImporter()->getUnprocessed('delete');
+    $this->assertEqual(count($deletes), 5, 'Importing configuration will delete 3 field instances and 2 fields.');
 
     // Import the content of the staging directory.
     $this->configImporter()->import();
diff --git a/core/modules/filter/lib/Drupal/filter/Entity/FilterFormat.php b/core/modules/filter/lib/Drupal/filter/Entity/FilterFormat.php
index 4b36306..e1ea563 100644
--- a/core/modules/filter/lib/Drupal/filter/Entity/FilterFormat.php
+++ b/core/modules/filter/lib/Drupal/filter/Entity/FilterFormat.php
@@ -238,7 +238,7 @@ public function postSave(EntityStorageInterface $storage, $update = TRUE) {
       // Clear the filter cache whenever a text format is updated.
       Cache::deleteTags(array('filter_format' => $this->id()));
     }
-    else {
+    elseif (!$this->isSyncing()) {
       // Default configuration of modules and installation profiles is allowed
       // to specify a list of user roles to grant access to for the new format;
       // apply the defined user role permissions when a new format is inserted
diff --git a/core/modules/image/image.module b/core/modules/image/image.module
index 472cad4..28a92e3 100644
--- a/core/modules/image/image.module
+++ b/core/modules/image/image.module
@@ -387,6 +387,7 @@ function image_filter_keyword($value, $current_pixels, $new_pixels) {
  */
 function image_entity_presave(EntityInterface $entity) {
   $field = FALSE;
+
   $entity_type_id = $entity->getEntityTypeId();
   if ($entity_type_id == 'field_instance_config') {
     $field = $entity->getField();
@@ -399,6 +400,10 @@ function image_entity_presave(EntityInterface $entity) {
     return;
   }
 
+  if ($field->isSyncing()) {
+    return;
+  }
+
   $fid = $entity->settings['default_image']['fid'];
   if ($fid) {
     $original_fid = isset($entity->original) ? $entity->original->settings['default_image']['fid'] : NULL;
diff --git a/core/modules/image/lib/Drupal/image/Entity/ImageStyle.php b/core/modules/image/lib/Drupal/image/Entity/ImageStyle.php
index 7bd7537..6ac64a6 100644
--- a/core/modules/image/lib/Drupal/image/Entity/ImageStyle.php
+++ b/core/modules/image/lib/Drupal/image/Entity/ImageStyle.php
@@ -105,7 +105,9 @@ public function postSave(EntityStorageInterface $storage, $update = TRUE) {
         // The old image style name needs flushing after a rename.
         $this->original->flush();
         // Update field instance settings if necessary.
-        static::replaceImageStyle($this);
+        if (!$this->isSyncing()) {
+          static::replaceImageStyle($this);
+        }
       }
       else {
         // Flush image style when updating without changing the name.
@@ -126,7 +128,7 @@ public static function postDelete(EntityStorageInterface $storage, array $entiti
       // Check whether field instance settings need to be updated.
       // In case no replacement style was specified, all image fields that are
       // using the deleted style are left in a broken state.
-      if ($new_id = $style->getReplacementID()) {
+      if (!$style->isSyncing() && $new_id = $style->getReplacementID()) {
         // The deleted ID is still set as originalID.
         $style->setName($new_id);
         static::replaceImageStyle($style);
diff --git a/core/modules/menu/menu.module b/core/modules/menu/menu.module
index e89feb8..c6e4e36 100644
--- a/core/modules/menu/menu.module
+++ b/core/modules/menu/menu.module
@@ -145,6 +145,11 @@ function menu_menu_insert(Menu $menu) {
   if (\Drupal::moduleHandler()->moduleExists('block')) {
     \Drupal::service('plugin.manager.block')->clearCachedDefinitions();
   }
+
+  if ($menu->isSyncing()) {
+    return;
+  }
+
   // Make sure the menu is present in the active menus variable so that its
   // items may appear in the menu active trail.
   // See menu_set_active_menu_names().
@@ -334,6 +339,9 @@ function menu_node_update(EntityInterface $node) {
  * Implements hook_node_type_insert().
  */
 function menu_node_type_insert(NodeTypeInterface $type) {
+  if ($type->isSyncing()) {
+    return;
+  }
   \Drupal::config('menu.entity.node.' . $type->id())
     ->set('available_menus', array('main'))
     ->set('parent', 'main:0')
@@ -344,6 +352,9 @@ function menu_node_type_insert(NodeTypeInterface $type) {
  * Implements hook_node_type_delete().
  */
 function menu_node_type_delete(NodeTypeInterface $type) {
+  if ($type->isSyncing()) {
+    return;
+  }
   \Drupal::config('menu.entity.node.' . $type->id())->delete();
 }
 
diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Entity/Vocabulary.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Entity/Vocabulary.php
index f5a7ba7..6222a1e 100644
--- a/core/modules/taxonomy/lib/Drupal/taxonomy/Entity/Vocabulary.php
+++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Entity/Vocabulary.php
@@ -102,7 +102,7 @@ public function postSave(EntityStorageInterface $storage, $update = TRUE) {
     if (!$update) {
       entity_invoke_bundle_hook('create', 'taxonomy_term', $this->id());
     }
-    elseif ($this->getOriginalId() != $this->id()) {
+    elseif ($this->getOriginalId() != $this->id() && !$this->isSyncing()) {
       // Reflect machine name changes in the definitions of existing 'taxonomy'
       // fields.
       $field_ids = array();
@@ -153,6 +153,13 @@ public static function preDelete(EntityStorageInterface $storage, array $entitie
   public static function postDelete(EntityStorageInterface $storage, array $entities) {
     parent::postDelete($storage, $entities);
 
+    // Reset caches.
+    $storage_controller->resetCache(array_keys($entities));
+
+    if (reset($entities)->isSyncing()) {
+      return;
+    }
+
     $vocabularies = array();
     foreach ($entities as $vocabulary) {
       $vocabularies[$vocabulary->id()] = $vocabulary->id();
