diff --git a/adminlib.php b/adminlib.php
index 76afb02e086d0f681dcfa10108e9f9cd03b484f3..fa1aaaf6eef4395ef4bbe75e084c4ca890db5e29 100644
--- a/adminlib.php
+++ b/adminlib.php
@@ -636,17 +636,18 @@ class workflow_settings {
                 \core\notification::add(
                     get_string('active_workflow_not_changeable', 'tool_lifecycle'),
                     \core\notification::WARNING);
-            } else {
-                if (!empty($data->id)) {
-                    $step = step_manager::get_step_instance($data->id);
+            }
+            if (!empty($data->id)) {
+                $step = step_manager::get_step_instance($data->id);
+                if (isset($data->instancename)) {
                     $step->instancename = $data->instancename;
-                } else {
-                    $step = step_subplugin::from_record($data);
                 }
-                step_manager::insert_or_update($step);
-                // Save local subplugin settings.
-                settings_manager::save_settings($step->id, settings_type::STEP, $form->subpluginname, $data);
+            } else {
+                $step = step_subplugin::from_record($data);
             }
+            step_manager::insert_or_update($step);
+            // Save local subplugin settings.
+            settings_manager::save_settings($step->id, settings_type::STEP, $form->subpluginname, $data, true);
         } else {
             $this->view_step_instance_form($form);
             return true;
diff --git a/classes/local/form/form_step_instance.php b/classes/local/form/form_step_instance.php
index 542817c8446ae647ec03b635aef5dc244ab7e745..8e64abce2d06b6b776024e0cc6f3e6842904626a 100644
--- a/classes/local/form/form_step_instance.php
+++ b/classes/local/form/form_step_instance.php
@@ -129,12 +129,7 @@ class form_step_instance extends \moodleform {
             $this->lib->extend_add_instance_form_definition($mform);
         }
 
-        // For active workflows, we do not want the form to be editable.
-        if ($this->workflowid && !workflow_manager::is_editable($this->workflowid)) {
-            $this->add_cancel_button();
-        } else {
-            $this->add_action_buttons();
-        }
+        $this->add_action_buttons();
     }
 
     /**
@@ -183,7 +178,13 @@ class form_step_instance extends \moodleform {
         // For active workflows, we do not want the form to be editable.
         if ($this->workflowid && !workflow_manager::is_editable($this->workflowid)) {
             // The group buttonar is the array of submit buttons. For inactive workflows this is only a cancel button.
-            $mform->hardFreezeAllVisibleExcept(array('buttonar'));
+            $notfreeze = ['buttonar'];
+            foreach ($this->lib->instance_settings() as $setting) {
+                if ($setting->editable) {
+                    $notfreeze[] = $setting->name;
+                }
+            }
+            $mform->hardFreezeAllVisibleExcept($notfreeze);
         }
     }
 
diff --git a/classes/local/form/form_trigger_instance.php b/classes/local/form/form_trigger_instance.php
index 71653a7fc74f44b8b2a15512f367691f66fd182d..0ac8f901d36af11d57dcd1334af56317e86bd220 100644
--- a/classes/local/form/form_trigger_instance.php
+++ b/classes/local/form/form_trigger_instance.php
@@ -135,12 +135,7 @@ class form_trigger_instance extends \moodleform {
             $this->lib->extend_add_instance_form_definition($mform);
         }
 
-        // For active workflows, we do not want the form to be editable.
-        if ($this->workflowid && !workflow_manager::is_editable($this->workflowid)) {
-            $this->add_cancel_button();
-        } else {
-            $this->add_action_buttons();
-        }
+        $this->add_action_buttons();
     }
 
     /**
@@ -186,7 +181,13 @@ class form_trigger_instance extends \moodleform {
         // For active workflows, we do not want the form to be editable.
         if ($this->workflowid && !workflow_manager::is_editable($this->workflowid)) {
             // The group buttonar is the array of submit buttons. For inactive workflows this is only a cancel button.
-            $mform->hardFreezeAllVisibleExcept(array('buttonar'));
+            $notfreeze = ['buttonar'];
+            foreach ($this->lib->instance_settings() as $setting) {
+                if ($setting->editable) {
+                    $notfreeze[] = $setting->name;
+                }
+            }
+            $mform->hardFreezeAllVisibleExcept($notfreeze);
         }
     }
 
diff --git a/classes/local/manager/settings_manager.php b/classes/local/manager/settings_manager.php
index 7e76238a773697f5c1f81892b320b42a34fb6277..4db7be7e7e1605779d732a183593beeabf6a41fc 100644
--- a/classes/local/manager/settings_manager.php
+++ b/classes/local/manager/settings_manager.php
@@ -23,6 +23,7 @@
  */
 namespace tool_lifecycle\local\manager;
 
+use tool_lifecycle\local\entity\workflow;
 use tool_lifecycle\settings_type;
 
 defined('MOODLE_INTERNAL') || die();
@@ -57,9 +58,11 @@ class settings_manager {
      * @param 'step'|'trigger' $type type of the subplugin.
      * @param string $subpluginname name of the subplugin.
      * @param mixed $data submitted data of the form.
+     * @param bool $accessvalidation whether to do only change settings that are editable once the workflow has started.
+     *          Then also calls the on_setting_changed listener. Defaults to false.
      * @throws \moodle_exception
      */
-    public static function save_settings($instanceid, $type, $subpluginname, $data) {
+    public static function save_settings($instanceid, $type, $subpluginname, $data, $accessvalidation = false) {
         global $DB;
         self::validate_type($type);
 
@@ -74,8 +77,12 @@ class settings_manager {
 
         if ($type == settings_type::TRIGGER) {
             $lib = lib_manager::get_trigger_lib($subpluginname);
+            $trigger = trigger_manager::get_instance($instanceid);
+            $wfeditable = workflow_manager::is_editable($trigger->workflowid);
         } else {
             $lib = lib_manager::get_step_lib($subpluginname);
+            $step = step_manager::get_step_instance($instanceid);
+            $wfeditable = workflow_manager::is_editable($step->workflowid);
         }
 
         $settingsfields = $lib->instance_settings();
@@ -83,6 +90,9 @@ class settings_manager {
             throw new \moodle_exception('id of the step instance has to be set!');
         }
         foreach ($settingsfields as $setting) {
+            if ($accessvalidation && !$wfeditable && !$setting->editable) {
+                continue;
+            }
             if (array_key_exists($setting->name, $data)) {
                 $value = $data[$setting->name];
                 // Needed for editor support.
@@ -105,8 +115,14 @@ class settings_manager {
                         'name' => $setting->name)
                 );
                 if ($record) {
-                    $record->value = $cleanedvalue;
-                    $DB->update_record('tool_lifecycle_settings', $record);
+                    if ($record->value != $cleanedvalue) {
+                        $oldvalue = $record->value;
+                        $record->value = $cleanedvalue;
+                        $DB->update_record('tool_lifecycle_settings', $record);
+                        if ($accessvalidation && !$wfeditable) {
+                            $lib->on_setting_changed($setting->name, $cleanedvalue, $oldvalue);
+                        }
+                    }
                 } else {
                     $newrecord = new \stdClass();
                     $newrecord->instanceid = $instanceid;
diff --git a/lang/de/tool_lifecycle.php b/lang/de/tool_lifecycle.php
index fa77816ec52ad1a4da05b7a4bdffd9fba24a66de..b3f2bcaa98309e0cd3ccb509f88dadafcb4fa349 100644
--- a/lang/de/tool_lifecycle.php
+++ b/lang/de/tool_lifecycle.php
@@ -51,7 +51,7 @@ $string['general_settings_header'] = 'Allgemeine Einstellungen';
 $string['followedby_none'] = 'Keine';
 $string['invalid_workflow'] = 'Ungültige Workflowkonfiguration';
 $string['invalid_workflow_details'] = 'Gehe zur Detailanzeige, um einen Trigger für diesen Workflow zu erstellen.';
-$string['active_workflow_not_changeable'] = 'Die Workflow-Instanz wurde bereits aktiviert. Es ist nicht mehr möglich, Schritte zu ändern.';
+$string['active_workflow_not_changeable'] = 'Die Workflow-Instanz wurde bereits aktiviert. Je nach Schritt-Typ können dessen Einstellungen eventuell noch geändert werden. Änderungen an Trigger-Instanzen wirken sich nicht auf bereits getriggerte Kurse aus.';
 $string['active_workflow_not_removeable'] = 'Die Workflow-Instanz ist aktiv. Es ist nicht möglich, sie zu entfernen.';
 $string['workflow_not_removeable'] = 'Es ist nicht möglich, diese Workflow-Instanz zu entfernen. Vielleicht hat sie noch laufende Prozesse?';
 $string['invalid_workflow_cannot_be_activated'] = 'Der Workflow kann nicht aktiviert werden, da die Workflowdefinition ungültig ist';
diff --git a/lang/en/tool_lifecycle.php b/lang/en/tool_lifecycle.php
index 420eb2665200454727ca2c6d5dc333c430b81316..eca85b7debb42330693857b2999168f67311b5f2 100644
--- a/lang/en/tool_lifecycle.php
+++ b/lang/en/tool_lifecycle.php
@@ -54,7 +54,7 @@ $string['general_settings_header'] = 'General settings';
 $string['followedby_none'] = 'None';
 $string['invalid_workflow'] = 'Invalid workflow configuration';
 $string['invalid_workflow_details'] = 'Go to details view, to create a trigger for this workflow';
-$string['active_workflow_not_changeable'] = 'The workflow instance was already activated. It is not possible to change any of its steps anymore.';
+$string['active_workflow_not_changeable'] = 'The workflow instance was already activated. Depending on the step type, some of its settings might be still editable. Changes to triggers will not affect already triggered courses.';
 $string['active_workflow_not_removeable'] = 'The workflow instance is active. It is not possible to remove it.';
 $string['workflow_not_removeable'] = 'It is not possible to remove this workflow instance. Maybe it still has running processes?';
 $string['invalid_workflow_cannot_be_activated'] = 'The workflow definition is invalid, thus it cannot be activated.';
diff --git a/step/createbackup/lib.php b/step/createbackup/lib.php
index 5c0fa5a0c4cf9fe0a9110c2d7ab42208ad884764..ae38c21cb9c40a4210ac831b603dcff45d0413e1 100644
--- a/step/createbackup/lib.php
+++ b/step/createbackup/lib.php
@@ -101,7 +101,7 @@ class createbackup extends libbase {
      */
     public function instance_settings() {
         return array(
-            new instance_setting('maximumbackupspercron', PARAM_INT),
+            new instance_setting('maximumbackupspercron', PARAM_INT, true),
         );
     }
 
diff --git a/step/deletecourse/lib.php b/step/deletecourse/lib.php
index 2480cf220b85033246dc246ba00ebd81019aa991..3503f159f53e5a9d96b863c1a402a0c996d59f3d 100644
--- a/step/deletecourse/lib.php
+++ b/step/deletecourse/lib.php
@@ -95,7 +95,7 @@ class deletecourse extends libbase {
      */
     public function instance_settings() {
         return array(
-            new instance_setting('maximumdeletionspercron', PARAM_INT),
+            new instance_setting('maximumdeletionspercron', PARAM_INT, true),
         );
     }
 
diff --git a/step/email/lib.php b/step/email/lib.php
index b2477417accffe99e6a1bbc8604ef2635c10cd35..89d64f955fb568e33e0dd0742ff65b31e4426bd3 100644
--- a/step/email/lib.php
+++ b/step/email/lib.php
@@ -221,10 +221,10 @@ class email extends libbase {
      */
     public function instance_settings() {
         return array(
-            new instance_setting('responsetimeout', PARAM_INT),
-            new instance_setting('subject', PARAM_TEXT),
-            new instance_setting('content', PARAM_RAW),
-            new instance_setting('contenthtml', PARAM_RAW),
+            new instance_setting('responsetimeout', PARAM_INT, false),
+            new instance_setting('subject', PARAM_TEXT, true),
+            new instance_setting('content', PARAM_RAW, true),
+            new instance_setting('contenthtml', PARAM_RAW, true),
         );
     }
 
diff --git a/step/lib.php b/step/lib.php
index f5cbb9faa2668260d784f6c2db43c84637b7c624..7209d1d3d5622341bab2ea2acf7e03cae4093282 100644
--- a/step/lib.php
+++ b/step/lib.php
@@ -107,6 +107,16 @@ abstract class libbase {
         return array();
     }
 
+    /**
+     * Is called when a setting is changed after a workflow is activated.
+     * @param string $settingname name of the setting
+     * @param mixed $newvalue the new value
+     * @param mixed $oldvalue the old value
+     */
+    public function on_setting_changed($settingname, $newvalue, $oldvalue) {
+
+    }
+
     /**
      * This method can be overriden, to add form elements to the form_step_instance.
      * It is called in definition().
@@ -149,14 +159,19 @@ class instance_setting {
     /** @var string param type of the setting, e.g. PARAM_INT */
     public $paramtype;
 
+    /** @var bool if editable after activation */
+    public $editable;
+
     /**
      * Create a local settings object.
      * @param string $name name of the setting
      * @param string $paramtype param type. Used for cleansing and parsing, e.g. PARAM_INT.
+     * @param bool $editable if setting is editable after activation
      */
-    public function __construct($name, $paramtype) {
+    public function __construct(string $name, string $paramtype, bool $editable = false) {
         $this->name = $name;
         $this->paramtype = $paramtype;
+        $this->editable = $editable;
     }
 
 }
diff --git a/trigger/categories/lib.php b/trigger/categories/lib.php
index acb296188e24a8d638185e0ab0f5c7e59f47b53b..64381756146aaf8b921f90126654e3ccd98fd103 100644
--- a/trigger/categories/lib.php
+++ b/trigger/categories/lib.php
@@ -103,8 +103,8 @@ class categories extends base_automatic {
      */
     public function instance_settings() {
         return array(
-            new instance_setting('categories', PARAM_SEQUENCE),
-            new instance_setting('exclude', PARAM_BOOL),
+            new instance_setting('categories', PARAM_SEQUENCE, true),
+            new instance_setting('exclude', PARAM_BOOL, true),
         );
     }
 
diff --git a/trigger/lib.php b/trigger/lib.php
index 5ec5ad787bd783f49a9067881211443630b1072f..3c01ffb7bc98d55f078e24af7f95b3f4b213065c 100644
--- a/trigger/lib.php
+++ b/trigger/lib.php
@@ -53,6 +53,16 @@ abstract class base {
         return array();
     }
 
+    /**
+     * Is called when a setting is changed after a workflow is activated.
+     * @param string $settingname name of the setting
+     * @param mixed $newvalue the new value
+     * @param mixed $oldvalue the old value
+     */
+    public function on_setting_changed($settingname, $newvalue, $oldvalue) {
+
+    }
+
     /**
      * This method can be overriden, to add form elements to the form_step_instance.
      * It is called in definition().
@@ -179,14 +189,19 @@ class instance_setting {
     /** @var string param type of the setting, e.g. PARAM_INT */
     public $paramtype;
 
+    /** @var bool if editable after activation */
+    public $editable;
+
     /**
      * Create a local settings object.
      * @param string $name name of the setting
      * @param string $paramtype param type. Used for cleansing and parsing, e.g. PARAM_INT.
+     * @param bool $editable if setting is editable after activation
      */
-    public function __construct($name, $paramtype) {
+    public function __construct(string $name, string $paramtype, bool $editable = false) {
         $this->name = $name;
         $this->paramtype = $paramtype;
+        $this->editable = $editable;
     }
 
 }
diff --git a/trigger/startdatedelay/lib.php b/trigger/startdatedelay/lib.php
index 7d0cd6491ddc67b1cccc63336eb7af071e138039..01e3d0ed6c5c65e3d11f0715a480314c42e17afa 100644
--- a/trigger/startdatedelay/lib.php
+++ b/trigger/startdatedelay/lib.php
@@ -80,7 +80,7 @@ class startdatedelay extends base_automatic {
      */
     public function instance_settings() {
         return array(
-            new instance_setting('delay', PARAM_INT)
+            new instance_setting('delay', PARAM_INT, true)
         );
     }