diff --git a/core/lib/Drupal/Core/Config/ConfigImporter.php b/core/lib/Drupal/Core/Config/ConfigImporter.php
index 5e11697..8888b4e 100644
--- a/core/lib/Drupal/Core/Config/ConfigImporter.php
+++ b/core/lib/Drupal/Core/Config/ConfigImporter.php
@@ -214,7 +214,9 @@ public function import() {
       //   https://drupal.org/node/2080823
       foreach (array('delete', 'create', 'update') as $op) {
         foreach ($this->getUnprocessed($op) as $name) {
-          $this->process($op, $name);
+          if ($this->checkOp($op, $name)) {
+            $this->process($op, $name);
+          }
         }
       }
       // Allow modules to react to a import.
@@ -260,6 +262,53 @@ protected function process($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 string $name
+   *   The name of the configuration to process.
+   *
+   * @throws \Drupal\Core\Config\ConfigImporterException
+   *
+   * @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) {
+          throw new ConfigImporterException(String::format('Update target "@name" is missing.', array('@name' => $name)));
+        }
+        break;
+    }
+    return TRUE;
+  }
+
+  /**
    * Writes a configuration change from the source to the target storage.
    *
    * @param string $op
@@ -328,7 +377,6 @@ protected function importInvokeOwner($op, $name) {
       $this->setProcessed($op, $name);
       return TRUE;
     }
-    return FALSE;
   }
 
   /**
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/config/lib/Drupal/config/Tests/ConfigImporterTest.php b/core/modules/config/lib/Drupal/config/Tests/ConfigImporterTest.php
index 8e99296..e679f5b 100644
--- a/core/modules/config/lib/Drupal/config/Tests/ConfigImporterTest.php
+++ b/core/modules/config/lib/Drupal/config/Tests/ConfigImporterTest.php
@@ -197,6 +197,184 @@ function testNew() {
   }
 
   /**
+   * Tests that secondary writes are overwritten.
+   */
+  function testSecondaryWritePrimaryFirst() {
+    $name_primary = 'config_test.dynamic.primary';
+    $name_secondary = 'config_test.dynamic.secondary';
+    $staging = $this->container->get('config.storage.staging');
+    $uuid = $this->container->get('uuid');
+
+    $values_primary = array(
+      'id' => 'primary',
+      'label' => 'Primary',
+      'weight' => 0,
+      'uuid' => $uuid->generate(),
+    );
+    $staging->write($name_primary, $values_primary);
+    $values_secondary = array(
+      'id' => 'secondary',
+      'label' => 'Secondary Sync',
+      'weight' => 0,
+      'uuid' => $uuid->generate(),
+      // Add a dependency on primary, to ensure that is synced first.
+      'dependencies' => array(
+        'entity' => array($name_primary),
+      )
+    );
+    $staging->write($name_secondary, $values_secondary);
+
+    // Import.
+    $this->configImporter->reset()->import();
+
+    $entity_storage = \Drupal::entityManager()->getStorage('config_test');
+    $primary = $entity_storage->load('primary');
+    $this->assertEqual($primary->id(), 'primary');
+    $this->assertEqual($primary->uuid(), $values_primary['uuid']);
+    $this->assertEqual($primary->label(), $values_primary['label']);
+    $secondary = $entity_storage->load('secondary');
+    $this->assertEqual($secondary->id(), 'secondary');
+    $this->assertEqual($secondary->uuid(), $values_secondary['uuid']);
+    $this->assertEqual($secondary->label(), $values_secondary['label']);
+  }
+
+  /**
+   * Tests that secondary writes are overwritten.
+   */
+  function testSecondaryWriteSecondaryFirst() {
+    $name_primary = 'config_test.dynamic.primary';
+    $name_secondary = 'config_test.dynamic.secondary';
+    $staging = $this->container->get('config.storage.staging');
+    $uuid = $this->container->get('uuid');
+
+    $values_primary = array(
+      'id' => 'primary',
+      'label' => 'Primary',
+      'weight' => 0,
+      'uuid' => $uuid->generate(),
+      // Add a dependency on secondary, so that is synced first.
+      'dependencies' => array(
+        'entity' => array($name_secondary),
+      )
+    );
+    $staging->write($name_primary, $values_primary);
+    $values_secondary = array(
+      'id' => 'secondary',
+      'label' => 'Secondary Sync',
+      'weight' => 0,
+      'uuid' => $uuid->generate(),
+    );
+    $staging->write($name_secondary, $values_secondary);
+
+    // Import.
+    $this->configImporter->reset()->import();
+
+    $entity_storage = \Drupal::entityManager()->getStorage('config_test');
+    $primary = $entity_storage->load('primary');
+    $this->assertEqual($primary->id(), 'primary');
+    $this->assertEqual($primary->uuid(), $values_primary['uuid']);
+    $this->assertEqual($primary->label(), $values_primary['label']);
+    $secondary = $entity_storage->load('secondary');
+    $this->assertEqual($secondary->id(), 'secondary');
+    $this->assertEqual($secondary->uuid(), $values_secondary['uuid']);
+    $this->assertEqual($secondary->label(), $values_secondary['label']);
+  }
+
+  /**
+   * Tests that secondary updates for deleted files work as expected.
+   */
+  function testSecondaryUpdateDeletedDeleterFirst() {
+    $name_deleter = 'config_test.dynamic.deleter';
+    $name_deletee = 'config_test.dynamic.deletee';
+    $storage = $this->container->get('config.storage');
+    $staging = $this->container->get('config.storage.staging');
+    $uuid = $this->container->get('uuid');
+
+    $values_deleter = array(
+      'id' => 'deleter',
+      'label' => 'Deleter',
+      'weight' => 0,
+      'uuid' => $uuid->generate(),
+    );
+    $storage->write($name_deleter, $values_deleter);
+    $values_deleter['label'] = 'Updated Deleter';
+    $staging->write($name_deleter, $values_deleter);
+    $values_deletee = array(
+      'id' => 'deletee',
+      'label' => 'Deletee',
+      'weight' => 0,
+      'uuid' => $uuid->generate(),
+      // Add a dependency on deleter, to make sure that is synced first.
+      'dependencies' => array(
+        'entity' => array($name_deleter),
+      )
+    );
+    $storage->write($name_deletee, $values_deletee);
+    $values_deletee['label'] = 'Updated Deletee';
+    $staging->write($name_deletee, $values_deletee);
+
+    // Import.
+    $this->configImporter->reset()->import();
+
+    $entity_storage = \Drupal::entityManager()->getStorage('config_test');
+    $deleter = $entity_storage->load('deleter');
+    $this->assertEqual($deleter->id(), 'deleter');
+    $this->assertEqual($deleter->uuid(), $values_deleter['uuid']);
+    $this->assertEqual($deleter->label(), $values_deleter['label']);
+    $deletee = $entity_storage->load('deletee');
+    $this->assertEqual($deletee->id(), 'deletee');
+    $this->assertEqual($deletee->uuid(), $values_deletee['uuid']);
+    $this->assertEqual($deletee->label(), $values_deletee['label']);
+  }
+
+  /**
+   * Tests that secondary updates for deleted files work as expected.
+   */
+  function testSecondaryUpdateDeletedDeleteeFirst() {
+    $name_deleter = 'config_test.dynamic.deleter';
+    $name_deletee = 'config_test.dynamic.deletee';
+    $storage = $this->container->get('config.storage');
+    $staging = $this->container->get('config.storage.staging');
+    $uuid = $this->container->get('uuid');
+
+    $values_deleter = array(
+      'id' => 'deleter',
+      'label' => 'Deleter',
+      'weight' => 0,
+      'uuid' => $uuid->generate(),
+      // Add a dependency on deletee, to make sure that is synced first.
+      'dependencies' => array(
+        'entity' => array($name_deletee),
+      ),
+    );
+    $storage->write($name_deleter, $values_deleter);
+    $values_deleter['label'] = 'Updated Deleter';
+    $staging->write($name_deleter, $values_deleter);
+    $values_deletee = array(
+      'id' => 'deletee',
+      'label' => 'Deletee',
+      'weight' => 0,
+      'uuid' => $uuid->generate(),
+    );
+    $storage->write($name_deletee, $values_deletee);
+    $values_deletee['label'] = 'Updated Deletee';
+    $staging->write($name_deletee, $values_deletee);
+
+    // Import.
+    $this->configImporter->reset()->import();
+
+    $entity_storage = \Drupal::entityManager()->getStorage('config_test');
+    $deleter = $entity_storage->load('deleter');
+    $this->assertEqual($deleter->id(), 'deleter');
+    $this->assertEqual($deleter->uuid(), $values_deleter['uuid']);
+    $this->assertEqual($deleter->label(), $values_deleter['label']);
+    $deletee = $entity_storage->load('deletee');
+    $this->assertEqual($deletee->id(), 'deletee');
+    $this->assertEqual($deletee->uuid(), $values_deletee['uuid']);
+    $this->assertEqual($deletee->label(), $values_deletee['label']);
+  }
+
+  /**
    * Tests updating of configuration during import.
    */
   function testUpdated() {
diff --git a/core/modules/config/tests/config_test/lib/Drupal/config_test/Entity/ConfigTest.php b/core/modules/config/tests/config_test/lib/Drupal/config_test/Entity/ConfigTest.php
index d5217bf..b244234 100644
--- a/core/modules/config/tests/config_test/lib/Drupal/config_test/Entity/ConfigTest.php
+++ b/core/modules/config/tests/config_test/lib/Drupal/config_test/Entity/ConfigTest.php
@@ -10,6 +10,7 @@
 use Drupal\Core\Config\Entity\ConfigEntityBase;
 use Drupal\config_test\ConfigTestInterface;
 use Drupal\Core\Config\Entity\ConfigEntityInterface;
+use Drupal\Core\Entity\EntityStorageInterface;
 
 /**
  * Defines the ConfigTest configuration entity.
@@ -109,6 +110,24 @@ public static function sort(ConfigEntityInterface $a, ConfigEntityInterface $b)
   /**
    * {@inheritdoc}
    */
+  public function postSave(EntityStorageInterface $storage, $update = TRUE) {
+    // Used to test secondary writes during config sync.
+    if ($this->id() == 'primary') {
+      $secondary = $storage->create(array(
+        'id' => 'secondary',
+        'label' => 'Secondary Default',
+      ));
+      $secondary->save();
+    }
+    if ($this->id() == 'deleter') {
+      $deletee = $storage->load('deletee');
+      $deletee->delete();
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
   public function calculateDependencies() {
     parent::calculateDependencies();
     foreach ($this->test_dependencies as $type => $deps) {
diff --git a/core/modules/entity_reference/entity_reference.module b/core/modules/entity_reference/entity_reference.module
index cce3e3f..846a723 100644
--- a/core/modules/entity_reference/entity_reference.module
+++ b/core/modules/entity_reference/entity_reference.module
@@ -72,6 +72,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..0728ebf 100644
--- a/core/modules/field/lib/Drupal/field/Tests/FieldImportDeleteTest.php
+++ b/core/modules/field/lib/Drupal/field/Tests/FieldImportDeleteTest.php
@@ -7,6 +7,8 @@
 
 namespace Drupal\field\Tests;
 
+use Drupal\Component\Utility\String;
+
 /**
  * Tests deleting fields and instances as part of config import.
  */
@@ -31,13 +33,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 +55,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 +67,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 365a8aa..2c475a5 100644
--- a/core/modules/filter/lib/Drupal/filter/Entity/FilterFormat.php
+++ b/core/modules/filter/lib/Drupal/filter/Entity/FilterFormat.php
@@ -239,7 +239,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 a57fe55..9367cf0 100644
--- a/core/modules/image/image.module
+++ b/core/modules/image/image.module
@@ -373,6 +373,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();
@@ -385,6 +386,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 76da041..47b5813 100644
--- a/core/modules/menu/menu.module
+++ b/core/modules/menu/menu.module
@@ -133,6 +133,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().
@@ -322,6 +327,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')
@@ -332,6 +340,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..ec46b6b 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->resetCache(array_keys($entities));
+
+    if (reset($entities)->isSyncing()) {
+      return;
+    }
+
     $vocabularies = array();
     foreach ($entities as $vocabulary) {
       $vocabularies[$vocabulary->id()] = $vocabulary->id();
