diff --git a/app/services/ci/pipeline_creation/cancel_redundant_pipelines_service.rb b/app/services/ci/pipeline_creation/cancel_redundant_pipelines_service.rb
index 443ebc666fe51e5bfe82c0755cea3b05a2c127ed..ad6ac3f91713ad2793a2a1388c4778c15f48ca5a 100644
--- a/app/services/ci/pipeline_creation/cancel_redundant_pipelines_service.rb
+++ b/app/services/ci/pipeline_creation/cancel_redundant_pipelines_service.rb
@@ -13,9 +13,13 @@ class CancelRedundantPipelinesService
       def initialize(pipeline)
         @pipeline = pipeline
         @project = @pipeline.project
+
+        @skipped_for_old_age      = 0
+        @conservatively_cancelled = 0
+        @aggressively_cancelled   = 0
+        @configured_to_not_cancel = 0
       end
 
-      # rubocop: disable CodeReuse/ActiveRecord
       def execute
         return if service_disabled?
         return if pipeline.parent_pipeline? # skip if child pipeline
@@ -35,7 +39,7 @@ def cancelable_status_pipeline_ids
           .with_status(Ci::Pipeline::CANCELABLE_STATUSES)
           .order_id_desc # Query the most recently created cancellable Pipelines
           .limit(MAX_CANCELLATIONS_PER_PIPELINE)
-          .pluck(:id)
+          .pluck(:id) # rubocop:disable CodeReuse/ActiveRecord
           .reverse # Once we have the most recent Pipelines, cancel oldest & upstreams first
       end
       strong_memoize_attr :cancelable_status_pipeline_ids
@@ -45,18 +49,13 @@ def ref_head_sha
       end
       strong_memoize_attr :ref_head_sha
 
-      # rubocop:disable Metrics/CyclomaticComplexity -- Keep logic tightly bound while this is still experimental
       def auto_cancel_all_pipelines_with_cancelable_statuses
-        skipped_for_old_age      = 0
-        conservatively_cancelled = 0
-        aggressively_cancelled   = 0
-        configured_to_not_cancel = 0
-
         cancelable_status_pipeline_ids.each_slice(ID_BATCH_SIZE) do |ids_batch|
           Ci::Pipeline.id_in(ids_batch).order_id_asc.each do |cancelable|
             case cancelable.source.to_sym
             when *Enums::Ci::Pipeline.ci_sources.keys
-              # Newer pipelines are not cancelable
+              # Newer pipelines are not cancelable. This doesn't normally occur
+              # but needs to be handled in asynchronous execution.
               next if cancelable.created_at >= pipeline.created_at
             when :parent_pipeline
               # Child pipelines are cancelable based on the root parent age
@@ -70,32 +69,13 @@ def auto_cancel_all_pipelines_with_cancelable_statuses
             next if cancelable.sha == ref_head_sha
 
             if cancelable.created_at < pipelines_created_after
-              skipped_for_old_age += 1
+              @skipped_for_old_age += 1
 
               next
             end
 
             # Cancel method based on configured strategy
-            case cancelable.auto_cancel_on_new_commit
-            when 'none'
-              # no-op
-
-              configured_to_not_cancel += 1
-            when 'conservative'
-              next unless conservative_cancellable_pipeline_ids(ids_batch).include?(cancelable.id)
-
-              conservatively_cancelled += 1
-
-              cancel_pipeline(cancelable, safe_cancellation: false)
-            when 'interruptible'
-
-              aggressively_cancelled += 1
-
-              cancel_pipeline(cancelable, safe_cancellation: true)
-            else
-              raise ArgumentError,
-                "Unknown auto_cancel_on_new_commit value: #{cancelable.auto_cancel_on_new_commit}"
-            end
+            configured_cancellation_for(cancelable)
           end
         end
 
@@ -103,24 +83,46 @@ def auto_cancel_all_pipelines_with_cancelable_statuses
           class: self.class.name,
           message: "Canceling redundant pipelines",
           cancellable_count: cancelable_status_pipeline_ids.count,
-          skipped_for_old_age: skipped_for_old_age,
-          conservatively_cancelled: conservatively_cancelled,
-          aggressively_cancelled: aggressively_cancelled,
-          configured_to_not_cancel: configured_to_not_cancel,
+          skipped_for_old_age: @skipped_for_old_age,
+          conservatively_cancelled: @conservatively_cancelled,
+          aggressively_cancelled: @aggressively_cancelled,
+          configured_to_not_cancel: @configured_to_not_cancel,
           canceled_by_pipeline_id: pipeline.id,
           project_id: pipeline.project_id,
           ref: pipeline.ref,
           sha: pipeline.sha
         )
       end
-      # rubocop:enable Metrics/CyclomaticComplexity
 
-      def conservative_cancellable_pipeline_ids(pipeline_ids)
-        strong_memoize_with(:conservative_cancellable_pipeline_ids, pipeline_ids) do
-          ::Ci::Pipeline.id_in(pipeline_ids).conservative_interruptible.ids
+      def configured_cancellation_for(cancelable)
+        case cancelable.auto_cancel_on_new_commit
+        when 'none'
+          # no-op
+
+          @configured_to_not_cancel += 1
+        when 'conservative'
+          return unless conservative_cancellable_pipeline_ids.include?(cancelable.id)
+
+          @conservatively_cancelled += 1
+
+          cancel_pipeline(cancelable, safe_cancellation: false)
+        when 'interruptible'
+
+          @aggressively_cancelled += 1
+
+          cancel_pipeline(cancelable, safe_cancellation: true)
+        else
+          raise ArgumentError,
+            "Unknown auto_cancel_on_new_commit value: #{cancelable.auto_cancel_on_new_commit}"
+        end
+      end
+
+      def conservative_cancellable_pipeline_ids
+        cancelable_status_pipeline_ids.each_slice(ID_BATCH_SIZE).with_object([]) do |ids_batch, conservative_ids|
+          conservative_ids.concat(::Ci::Pipeline.id_in(ids_batch).conservative_interruptible.ids) # rubocop:disable CodeReuse/ActiveRecord
         end
       end
-      # rubocop: enable CodeReuse/ActiveRecord
+      strong_memoize_attr :conservative_cancellable_pipeline_ids
 
       def cancel_pipeline(cancelable_pipeline, safe_cancellation:)
         Gitlab::AppLogger.info(