diff --git a/qa/qa/runtime/env.rb b/qa/qa/runtime/env.rb
index 84f5f56a5830bd3fde9fef76f1bd8267eb365654..bc96ef81f85170aa011901247d10a9a84b5fe79c 100644
--- a/qa/qa/runtime/env.rb
+++ b/qa/qa/runtime/env.rb
@@ -741,10 +741,20 @@ def parallel_processes
         end.to_i
       end
 
+      # Execution was started by parallel runner
+      #
+      # @return [Boolean]
       def parallel_run?
         enabled?(ENV["QA_PARALLEL_RUN"], default: false)
       end
 
+      # Execute tests in multiple parallel processes
+      #
+      # @return [Boolean]
+      def run_in_parallel?
+        enabled?(ENV["QA_RUN_IN_PARALLEL"], default: false)
+      end
+
       private
 
       def remote_grid_credentials
diff --git a/qa/qa/specs/parallel_runner.rb b/qa/qa/specs/parallel_runner.rb
index b3349b985b599096a7964c30db78554299331ebc..566fe91c50cc17a1405fabea09b0537bf663851d 100644
--- a/qa/qa/specs/parallel_runner.rb
+++ b/qa/qa/specs/parallel_runner.rb
@@ -1,6 +1,5 @@
 # frozen_string_literal: true
 
-require "parallel_tests"
 require "etc"
 
 module QA
@@ -26,6 +25,8 @@ def run(rspec_args)
 
           args.push("--", *rspec_args) unless rspec_args.empty?
 
+          Runtime::Logger.debug("Using parallel runner to trigger tests with arguments: '#{args}'")
+
           set_environment!
           perform_global_setup!
 
diff --git a/qa/qa/specs/runner.rb b/qa/qa/specs/runner.rb
index 431a7e3fc10a8639a299e90ad70f57c7ae1e8833..474f8ea382538fa7a9004c1457e05ce5eec576df 100644
--- a/qa/qa/specs/runner.rb
+++ b/qa/qa/specs/runner.rb
@@ -74,8 +74,8 @@ def run_rspec(args)
         elsif Runtime::Scenario.attributes[:test_metadata_only]
           test_metadata_only(args)
         elsif Runtime::Env.knapsack?
-          KnapsackRunner.run(args.flatten, parallel: parallel_run?) { |status| abort if status.nonzero? }
-        elsif !rspec_retried? && parallel_run?
+          KnapsackRunner.run(args.flatten, parallel: run_in_parallel?) { |status| abort if status.nonzero? }
+        elsif run_in_parallel?
           ParallelRunner.run(args.flatten)
         elsif Runtime::Scenario.attributes[:loop]
           LoopRunner.run(args.flatten)
@@ -101,6 +101,17 @@ def count_examples_only(args)
         raise e, "Failed to detect example count, error: '#{e}'.\nOut: '#{out.string}'\nErr: #{err.string}"
       end
 
+      # Trigger tests using parallel runner
+      #
+      # @return [Boolean]
+      def run_in_parallel?
+        return @parallel if defined?(@parallel)
+
+        # Do not use parallel with retry as parallel_tests is not capable to correctly detect
+        # groups of tests when `--only-failures` parameter is used
+        @parallel = (Runtime::Scenario.attributes[:parallel] || Runtime::Env.run_in_parallel?) && !rspec_retried?
+      end
+
       def test_metadata_only(args)
         args.unshift('--dry-run')
 
@@ -120,7 +131,7 @@ def test_metadata_only(args)
 
       def configure_default_formatters!(args)
         default_formatter_file_name = "tmp/rspec-#{ENV['CI_JOB_ID'] || 'local'}-retried-#{rspec_retried?}"
-        filename = if parallel_run?
+        filename = if run_in_parallel?
                      rspec_retried? ? default_formatter_file_name : "#{default_formatter_file_name}-$TEST_ENV_NUMBER"
                    else
                      default_formatter_file_name