diff --git a/core/includes/form.inc b/core/includes/form.inc
index 9d253351e2..32309a1882 100644
--- a/core/includes/form.inc
+++ b/core/includes/form.inc
@@ -757,12 +757,45 @@ function batch_set($batch_definition) {
     else {
       // The set is being added while the batch is running. Insert the new set
       // right after the current one to ensure execution order, and store its
-      // operations in a queue.
-      $index = $batch['current_set'] + 1;
-      $slice1 = array_slice($batch['sets'], 0, $index);
-      $slice2 = array_slice($batch['sets'], $index);
-      $batch['sets'] = array_merge($slice1, [$batch_set], $slice2);
-      _batch_populate_queue($batch, $index);
+      // operations in a queue. If multiple sets are being added while the batch
+      // is running ensure that each new one will be appended instead of
+      // prepended.
+      $append_after_index = $batch['current_set'];
+      foreach ($batch['sets'] as $index => $set) {
+        if ($index > $append_after_index) {
+          if (isset($set['appended_after_index'])) {
+            $append_after_index = $index;
+          }
+          else {
+            break;
+          }
+        }
+      }
+      $batch_set['appended_after_index'] = $append_after_index;
+
+      $new_set_index = count($batch['sets']);
+      $new_sets = [];
+
+      // Iterate by reference over the existing batch sets and assign them by
+      // reference in the new batch sets array in order not to break a retrieved
+      // reference to the current set. Among other places a reference to the
+      // current set is being retrieved in _batch_process(). We have to preserve
+      // the original indexes as they are used to generate the queue name of
+      // each batch set, as if we do not preserve the indexes of the existing
+      // batch sets the operations of the new batch will be queued in the queue
+      // of a previous batch set, because without index preservation we will be
+      // using not a new, but an existing and already used index for the new
+      // batch set.
+      // @see _batch_populate_queue().
+      foreach ($batch['sets'] as $index => &$set) {
+        $new_sets[$index] = &$set;
+        if ($index == $append_after_index) {
+          $new_sets[$new_set_index] = $batch_set;
+        }
+      }
+
+      $batch['sets'] = $new_sets;
+      _batch_populate_queue($batch, $new_set_index);
     }
   }
 }
diff --git a/core/modules/system/tests/src/Functional/Batch/ProcessingTest.php b/core/modules/system/tests/src/Functional/Batch/ProcessingTest.php
index 2d7c7ae01c..c18355f81f 100644
--- a/core/modules/system/tests/src/Functional/Batch/ProcessingTest.php
+++ b/core/modules/system/tests/src/Functional/Batch/ProcessingTest.php
@@ -248,11 +248,11 @@ public function _resultStack($id, $value = 0) {
         $stack = array_merge($stack, $this->_resultStack('batch_1'));
         $stack[] = 'submit handler 2';
         $stack[] = 'value = ' . ($value + 1);
-        $stack = array_merge($stack, $this->_resultStack('batch_2'));
         $stack[] = 'submit handler 3';
         $stack[] = 'value = ' . ($value + 2);
         $stack[] = 'submit handler 4';
         $stack[] = 'value = ' . ($value + 3);
+        $stack = array_merge($stack, $this->_resultStack('batch_2'));
         $stack = array_merge($stack, $this->_resultStack('batch_3'));
         break;
     }
