diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc
index eb9dff9..e7d4bbf 100644
--- a/core/includes/install.core.inc
+++ b/core/includes/install.core.inc
@@ -1642,6 +1642,11 @@ function install_finished(&$install_state) {
   $output = '<p>' . st('Congratulations, you installed @drupal!', array('@drupal' => drupal_install_profile_distribution_name())) . '</p>';
   $output .= '<p>' . (isset($messages['error']) ? st('Review the messages above before visiting <a href="@url">your new site</a>.', array('@url' => url(''))) : st('<a href="@url">Visit your new site</a>.', array('@url' => url('')))) . '</p>';
 
+  // Populate the cron key variable.
+  $cron_key = drupal_hash_base64(drupal_random_bytes(55));
+  config('system.cron')
+    ->set('cron_key', $cron_key)
+    ->save();
   // Run cron to populate update status tables (if available) so that users
   // will be warned if they've installed an out of date Drupal version.
   // Will also trigger indexing of profile-supplied content or feeds.
diff --git a/core/lib/Drupal/Core/Config/DatabaseStorage.php b/core/lib/Drupal/Core/Config/DatabaseStorage.php
index c736245..def83e4 100644
--- a/core/lib/Drupal/Core/Config/DatabaseStorage.php
+++ b/core/lib/Drupal/Core/Config/DatabaseStorage.php
@@ -13,15 +13,17 @@ class DatabaseStorage extends StorageBase {
   /**
    * Implements StorageInterface::read().
    */
-  public function read() {
+  public function read(&$isNew = NULL) {
     // There are situations, like in the installer, where we may attempt a
     // read without actually having the database available. In this case,
     // catch the exception and just return an empty array so the caller can
     // handle it if need be.
     $data = array();
+    $isNew = TRUE;
     try {
       $raw = db_query('SELECT data FROM {config} WHERE name = :name', array(':name' => $this->name))->fetchField();
       if ($raw !== FALSE) {
+        $isNew = FALSE;
         $data = $this->decode($raw);
       }
     }
diff --git a/core/lib/Drupal/Core/Config/DrupalConfig.php b/core/lib/Drupal/Core/Config/DrupalConfig.php
index f5a9220..6b3dca7 100644
--- a/core/lib/Drupal/Core/Config/DrupalConfig.php
+++ b/core/lib/Drupal/Core/Config/DrupalConfig.php
@@ -25,6 +25,20 @@ class DrupalConfig {
   protected $data = array();
 
   /**
+   * The original data of the configuration object.
+   *
+   * @var array
+   */
+  protected $original = array();
+
+  /**
+   * TRUE when this is new configuration ie doesnt exist in the active store.
+   *
+   * @var boolan
+   */
+  protected $isNew;
+
+  /**
    * Constructs a DrupalConfig object.
    *
    * @param StorageInterface $storage
@@ -41,8 +55,12 @@ class DrupalConfig {
    * Reads config data from the active store into our object.
    */
   public function read() {
-    $data = $this->storage->read();
-    $this->setData($data !== FALSE ? $data : array());
+    $data = $this->storage->read($this->isNew);
+    if ($data === FALSE) {
+      $data = array();
+    }
+    $this->original = $data;
+    $this->setData($data);
     return $this;
   }
 
@@ -205,8 +223,14 @@ class DrupalConfig {
 
   /**
    * Saves the configuration object.
+   *
+   * This invokes hook_config_presave() and related hooks. If you really need
+   * to bypass those (for example saving a config without fully bootstrapping)
+   * call the storage write directly but note that doing so might result in a
+   * broken system.
    */
   public function save() {
+    $this->invoke('config_presave');
     $this->storage->write($this->data);
   }
 
@@ -214,7 +238,24 @@ class DrupalConfig {
    * Deletes the configuration object.
    */
   public function delete() {
-    $this->data = array();
+    $this->invoke('config_delete');
     $this->storage->delete();
+    $this->data = array();
+    $this->original = array();
+  }
+
+  /**
+   * Invokes hooks.
+   */
+  protected function invoke($hook) {
+    if (drupal_bootstrap() < DRUPAL_BOOTSTRAP_CODE) {
+      throw new InvokeException('Can not save without modules loaded.');
+    }
+    module_invoke_all($hook, $this->data, $this->original, $this->isNew, $this);
+    $part = strtok($this->storage->getName(), '.');
+    do {
+      $hook .= '__' . $part;
+      module_invoke_all($hook, $this->data, $this->original, $this->isNew, $this);
+    } while ($part = strtok('.'));
   }
 }
diff --git a/core/lib/Drupal/Core/Config/InvokeException.php b/core/lib/Drupal/Core/Config/InvokeException.php
new file mode 100644
index 0000000..2bf1c63
--- /dev/null
+++ b/core/lib/Drupal/Core/Config/InvokeException.php
@@ -0,0 +1,8 @@
+<?php
+
+namespace Drupal\Core\Config;
+
+/**
+ * @todo
+ */
+class InvokeException extends ConfigException {}
diff --git a/core/lib/Drupal/Core/Config/StorageInterface.php b/core/lib/Drupal/Core/Config/StorageInterface.php
index 43141a5..4303bd2 100644
--- a/core/lib/Drupal/Core/Config/StorageInterface.php
+++ b/core/lib/Drupal/Core/Config/StorageInterface.php
@@ -23,7 +23,7 @@ interface StorageInterface {
   /**
    * Reads the configuration data from the storage.
    */
-  function read();
+  function read(&$isNew = NULL);
 
   /**
    * Copies the configuration data from the storage into a file.
diff --git a/core/modules/image/image.module b/core/modules/image/image.module
index 973f36a..bff1f2a 100644
--- a/core/modules/image/image.module
+++ b/core/modules/image/image.module
@@ -326,41 +326,45 @@ function image_file_predelete(File $file) {
 }
 
 /**
- * Implements hook_image_style_save().
+ * Implements hook_config_presave_image__style().
  */
-function image_image_style_save($style) {
-  if (isset($style['old_name']) && $style['old_name'] != $style['name']) {
-    $instances = field_read_instances();
-    // Loop through all fields searching for image fields.
-    foreach ($instances as $instance) {
-      if ($instance['widget']['module'] == 'image') {
-        $instance_changed = FALSE;
-        foreach ($instance['display'] as $view_mode => $display) {
-          // Check if the formatter involves an image style.
-          if ($display['type'] == 'image' && $display['settings']['image_style'] == $style['old_name']) {
-            // Update display information for any instance using the image
-            // style that was just deleted.
-            $instance['display'][$view_mode]['settings']['image_style'] = $style['name'];
-            $instance_changed = TRUE;
-          }
-        }
-        if ($instance['widget']['settings']['preview_image_style'] == $style['old_name']) {
-          $instance['widget']['settings']['preview_image_style'] = $style['name'];
+function image_config_presave__image__style($style, $original, $is_new) {
+  if (!$is_new && $style != $original) {
+    _image_effects_changed($style, $original);
+  }
+}
+
+function _image_effects_changed($style, $original) {
+  $instances = field_read_instances();
+  // Loop through all fields searching for image fields.
+  foreach ($instances as $instance) {
+    if ($instance['widget']['module'] == 'image') {
+      $instance_changed = FALSE;
+      foreach ($instance['display'] as $view_mode => $display) {
+        // Check if the formatter involves an image style.
+        if ($display['type'] == 'image' && $display['settings']['image_style'] == $original['name']) {
+          // Update display information for any instance using the image
+          // style that was just deleted.
+          $instance['display'][$view_mode]['settings']['image_style'] = $style['name'];
           $instance_changed = TRUE;
         }
-        if ($instance_changed) {
-          field_update_instance($instance);
-        }
+      }
+      if ($instance['widget']['settings']['preview_image_style'] == $original['name']) {
+        $instance['widget']['settings']['preview_image_style'] = $style['name'];
+        $instance_changed = TRUE;
+      }
+      if ($instance_changed) {
+        field_update_instance($instance);
       }
     }
   }
 }
 
 /**
- * Implements hook_image_style_delete().
+ * Implements hook_config_delete_image__style().
  */
-function image_image_style_delete($style) {
-  image_image_style_save($style);
+function image_config_delete__image__style($style, $original) {
+  _image_effects_changed($style, $original);
 }
 
 /**
@@ -586,12 +590,6 @@ function image_style_save($style) {
     $config->set('effects', array());
   }
   $config->save();
-  // @todo is_new must only be set when the configuration object did not exist
-  //   yet.
-  $style['is_new'] = TRUE;
-
-  // Let other modules update as necessary on save.
-  module_invoke_all('image_style_save', $style);
 
   // Clear all caches and flush.
   image_style_flush($style);
@@ -614,13 +612,9 @@ function image_style_delete($style, $replacement_style_name = '') {
   image_style_flush($style);
 
   $config = config('image.style.' . $style['name']);
+  $config->set('name', $replacement_style_name);
   $config->delete();
 
-  // Let other modules update as necessary on save.
-  $style['old_name'] = $style['name'];
-  $style['name'] = $replacement_style_name;
-  module_invoke_all('image_style_delete', $style);
-
   return TRUE;
 }
 
diff --git a/core/modules/system/system.api.php b/core/modules/system/system.api.php
index ed5b7a0..4772d91 100644
--- a/core/modules/system/system.api.php
+++ b/core/modules/system/system.api.php
@@ -4265,5 +4265,32 @@ function hook_filetransfer_info_alter(&$filetransfer_info) {
 }
 
 /**
+ * Validate and react before a config object is saved.
+ *
+ * This is not a single hook but a family of hooks. For example, when
+ * image.style.large is saved
+ * - hook_config_presave
+ * - hook_config_presave__image
+ * - hook_config_presave__image__style
+ * - hook_config_presave__image__style__large
+ * is called.
+ *
+ * @param $data
+ *   The configuration data being saved.
+ * @param $original
+ *   The original configuration data.
+ * @param $is_new
+ *   TRUE if the configuration does not exist in the active store, FALSE if
+ *   it does.
+ * @param $config
+ *   The config object itself.
+ */
+function hook_config_presave($data, $original, $is_new, $config) {
+  if (!$is_new && $data != $original) {
+    _image_effects_changed($data, $original);
+  }
+}
+
+/**
  * @} End of "addtogroup hooks".
  */
diff --git a/core/modules/system/system.install b/core/modules/system/system.install
index 84822c7..83570dd 100644
--- a/core/modules/system/system.install
+++ b/core/modules/system/system.install
@@ -517,12 +517,6 @@ function system_install() {
     ->condition('type', 'theme')
     ->condition('name', 'stark')
     ->execute();
-
-  // Populate the cron key variable.
-  $cron_key = drupal_hash_base64(drupal_random_bytes(55));
-  config('system.cron')
-    ->set('cron_key', $cron_key)
-    ->save();
 }
 
 /**
