diff --git a/app/workers/concerns/security/orchestration_configuration_bot_management_for_namespaces.rb b/app/workers/concerns/security/orchestration_configuration_bot_management_for_namespaces.rb
new file mode 100644
index 0000000000000000000000000000000000000000..72e527f478c10c52f282773b4e9df86cea5ca6c9
--- /dev/null
+++ b/app/workers/concerns/security/orchestration_configuration_bot_management_for_namespaces.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+module Security
+  module OrchestrationConfigurationBotManagementForNamespaces
+    extend ActiveSupport::Concern
+
+    PROJECTS_BATCH_SYNC_DELAY = 1.second
+
+    included do
+      feature_category :security_policy_management
+      urgency :low
+      concurrency_limit -> { 200 }
+    end
+
+    def perform(namespace_id, current_user_id)
+      namespace = Namespace.find_by_id(namespace_id)
+      return unless namespace
+
+      return unless User.id_exists?(current_user_id)
+
+      project_ids = namespace.security_orchestration_policy_configuration.all_project_ids
+
+      worker.bulk_perform_in_with_contexts(
+        PROJECTS_BATCH_SYNC_DELAY,
+        project_ids,
+        arguments_proc: ->(project_id) { [project_id, current_user_id] },
+        context_proc: ->(namespace) { { namespace: namespace } }
+      )
+
+      after_perform(namespace, current_user_id)
+    end
+
+    def after_perform(namespace, current_user_id); end
+  end
+end
diff --git a/config/sidekiq_queues.yml b/config/sidekiq_queues.yml
index 582d299ffc2ab7b600f753ccd190583d639e38e1..cc1d6edf9d8f2198f71d63844b8cb414e08c26d3 100644
--- a/config/sidekiq_queues.yml
+++ b/config/sidekiq_queues.yml
@@ -859,6 +859,8 @@
   - 1
 - - security_orchestration_configuration_create_bot
   - 1
+- - security_orchestration_configuration_create_bot_for_namespace
+  - 1
 - - security_orchestration_configuration_remove_bot
   - 1
 - - security_orchestration_configuration_remove_bot_for_namespace
diff --git a/ee/app/services/security/orchestration/assign_service.rb b/ee/app/services/security/orchestration/assign_service.rb
index a40b6dd10ec58aafa35cd8e9f1022aeb069f96fa..3e6d30d314b02fc6348fe0f79b7674a29f643e23 100644
--- a/ee/app/services/security/orchestration/assign_service.rb
+++ b/ee/app/services/security/orchestration/assign_service.rb
@@ -114,6 +114,14 @@ def policy_project_id
       def create_security_policy_project_bot
         if container.is_a?(Project)
           Security::OrchestrationConfigurationCreateBotWorker.perform_async(container.id, current_user.id)
+        else
+          create_bot_for_namespace
+        end
+      end
+
+      def create_bot_for_namespace
+        if Feature.enabled?(:security_policy_bot_worker, container)
+          Security::OrchestrationConfigurationCreateBotForNamespaceWorker.perform_async(container.id, current_user.id)
         else
           container.security_orchestration_policy_configuration.all_project_ids.each do |project_id|
             Security::OrchestrationConfigurationCreateBotWorker.perform_async(project_id, current_user.id)
diff --git a/ee/app/services/security/orchestration/unassign_service.rb b/ee/app/services/security/orchestration/unassign_service.rb
index 6dfd081621c3041e25be5a8de874b1586fb541f1..3e9d322f06a1e938ef7ab72e34e7d34e79b8c943 100644
--- a/ee/app/services/security/orchestration/unassign_service.rb
+++ b/ee/app/services/security/orchestration/unassign_service.rb
@@ -3,6 +3,8 @@
 module Security
   module Orchestration
     class UnassignService < ::BaseContainerService
+      include Gitlab::Utils::StrongMemoize
+
       def execute(delete_bot: true)
         return error(_('Policy project doesn\'t exist')) unless security_orchestration_policy_configuration
 
@@ -10,7 +12,9 @@ def execute(delete_bot: true)
 
         remove_bot(security_orchestration_policy_configuration) if delete_bot
 
-        delete_configuration(security_orchestration_policy_configuration, old_policy_project)
+        delete_configuration(security_orchestration_policy_configuration, old_policy_project) if delete_configuration?
+
+        success
       end
 
       private
@@ -20,8 +24,6 @@ def execute(delete_bot: true)
       def delete_configuration(configuration, old_policy_project)
         Security::DeleteOrchestrationConfigurationWorker.perform_async(
           configuration.id, current_user.id, old_policy_project.id)
-
-        success
       end
 
       def success
@@ -33,7 +35,7 @@ def error(message)
       end
 
       def remove_bot(security_orchestration_policy_configuration)
-        if container.is_a?(Project)
+        if project?
           Security::OrchestrationConfigurationRemoveBotWorker.perform_async(container.id, current_user.id)
         else
           remove_bot_for_namespace(security_orchestration_policy_configuration)
@@ -41,7 +43,7 @@ def remove_bot(security_orchestration_policy_configuration)
       end
 
       def remove_bot_for_namespace(security_orchestration_policy_configuration)
-        if Feature.enabled?(:security_policy_bot_worker, container)
+        if namespace_worker_enabled?
           Security::OrchestrationConfigurationRemoveBotForNamespaceWorker.perform_async(container.id, current_user.id)
         else
           security_orchestration_policy_configuration.all_project_ids.each do |project_id|
@@ -49,6 +51,20 @@ def remove_bot_for_namespace(security_orchestration_policy_configuration)
           end
         end
       end
+
+      def namespace_worker_enabled?
+        Feature.enabled?(:security_policy_bot_worker, container)
+      end
+      strong_memoize_attr :namespace_worker_enabled?
+
+      def project?
+        container.is_a?(Project)
+      end
+      strong_memoize_attr :project?
+
+      def delete_configuration?
+        project? || !namespace_worker_enabled?
+      end
     end
   end
 end
diff --git a/ee/app/workers/all_queues.yml b/ee/app/workers/all_queues.yml
index 815e36b6d88e8f7b985c675a4a574684228665e9..5e69d0b3a399313d4fb2f2bc84deb1fd29c325c1 100644
--- a/ee/app/workers/all_queues.yml
+++ b/ee/app/workers/all_queues.yml
@@ -3043,6 +3043,16 @@
   :idempotent: true
   :tags: []
   :queue_namespace:
+- :name: security_orchestration_configuration_create_bot_for_namespace
+  :worker_name: Security::OrchestrationConfigurationCreateBotForNamespaceWorker
+  :feature_category: :security_policy_management
+  :has_external_dependencies: false
+  :urgency: :low
+  :resource_boundary: :unknown
+  :weight: 1
+  :idempotent: true
+  :tags: []
+  :queue_namespace:
 - :name: security_orchestration_configuration_remove_bot
   :worker_name: Security::OrchestrationConfigurationRemoveBotWorker
   :feature_category: :security_policy_management
diff --git a/ee/app/workers/security/orchestration_configuration_create_bot_for_namespace_worker.rb b/ee/app/workers/security/orchestration_configuration_create_bot_for_namespace_worker.rb
new file mode 100644
index 0000000000000000000000000000000000000000..dd4672ae67ccd6930a7853d87085ee403ca0a677
--- /dev/null
+++ b/ee/app/workers/security/orchestration_configuration_create_bot_for_namespace_worker.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module Security
+  class OrchestrationConfigurationCreateBotForNamespaceWorker
+    include ApplicationWorker
+    include Security::OrchestrationConfigurationBotManagementForNamespaces
+
+    data_consistency :sticky
+    idempotent!
+
+    def worker
+      Security::OrchestrationConfigurationCreateBotWorker
+    end
+  end
+end
diff --git a/ee/app/workers/security/orchestration_configuration_remove_bot_for_namespace_worker.rb b/ee/app/workers/security/orchestration_configuration_remove_bot_for_namespace_worker.rb
index 3da5ca9a36457a6b4363e0ffc43a74fe820d0dd4..3af4ed813f8f3e8cbc2c88b73cce87ccb0014086 100644
--- a/ee/app/workers/security/orchestration_configuration_remove_bot_for_namespace_worker.rb
+++ b/ee/app/workers/security/orchestration_configuration_remove_bot_for_namespace_worker.rb
@@ -3,30 +3,35 @@
 module Security
   class OrchestrationConfigurationRemoveBotForNamespaceWorker
     include ApplicationWorker
+    include Security::OrchestrationConfigurationBotManagementForNamespaces
 
-    PROJECTS_BATCH_SYNC_DELAY = 1.second
-
-    feature_category :security_policy_management
     data_consistency :sticky
-    urgency :low
     idempotent!
 
-    concurrency_limit -> { 200 }
+    def worker
+      Security::OrchestrationConfigurationRemoveBotWorker
+    end
+
+    def after_perform(namespace, current_user_id)
+      delete_configuration(namespace, current_user_id)
+    end
 
-    def perform(namespace_id, current_user_id)
-      namespace = Namespace.find_by_id(namespace_id)
-      return unless namespace
+    private
 
-      return unless User.id_exists?(current_user_id)
+    def delete_configuration(namespace, current_user_id)
+      old_policy_project = old_policy_project(namespace)
+      configuration = configuration(namespace)
 
-      project_ids = namespace.security_orchestration_policy_configuration.all_project_ids
+      Security::DeleteOrchestrationConfigurationWorker.perform_async(
+        configuration.id, current_user_id, old_policy_project.id)
+    end
+
+    def configuration(namespace)
+      namespace.security_orchestration_policy_configuration
+    end
 
-      Security::OrchestrationConfigurationRemoveBotWorker.bulk_perform_in_with_contexts(
-        PROJECTS_BATCH_SYNC_DELAY,
-        project_ids,
-        arguments_proc: ->(project_id) { [project_id, current_user_id] },
-        context_proc: ->(namespace) { { namespace: namespace } }
-      )
+    def old_policy_project(namespace)
+      namespace.security_orchestration_policy_configuration.security_policy_management_project
     end
   end
 end
diff --git a/ee/spec/services/security/orchestration/assign_service_spec.rb b/ee/spec/services/security/orchestration/assign_service_spec.rb
index 610a5252a04ac4041d5a5cabb05d4ceb29f4d1c7..df764d9314f20a42b1ba667bc2d0185cbf65291d 100644
--- a/ee/spec/services/security/orchestration/assign_service_spec.rb
+++ b/ee/spec/services/security/orchestration/assign_service_spec.rb
@@ -281,8 +281,29 @@
       let(:another_container) { another_namespace }
 
       it_behaves_like 'executes assign service'
-      it_behaves_like 'triggers bot user create worker' do
-        let!(:expected_projects) { create_list(:project, 2, group: container) }
+
+      context 'when the `security_policy_bot_worker` feature flag is disabled' do
+        before do
+          stub_feature_flags(security_policy_bot_worker: false)
+        end
+
+        it_behaves_like 'triggers bot user create worker' do
+          let!(:expected_projects) { create_list(:project, 2, group: container) }
+        end
+      end
+
+      context 'when the `security_policy_bot_worker` feature flag is enabled' do
+        context 'with owner access' do
+          before do
+            container.add_owner(current_user)
+          end
+
+          it 'triggers the project bot user create for namespace worker' do
+            expect(Security::OrchestrationConfigurationCreateBotForNamespaceWorker).to receive(:perform_async).with(container.id, current_user.id)
+
+            expect(service).to be_success
+          end
+        end
       end
 
       describe 'redundant policy configurations within namespace' do
diff --git a/ee/spec/services/security/orchestration/unassign_service_spec.rb b/ee/spec/services/security/orchestration/unassign_service_spec.rb
index b85a6086ec2796cd67f7c93d4d93b04518c45df9..87cf035e5385585be0d7b7428781125a135274c6 100644
--- a/ee/spec/services/security/orchestration/unassign_service_spec.rb
+++ b/ee/spec/services/security/orchestration/unassign_service_spec.rb
@@ -173,19 +173,18 @@
           end
         end
 
-        it 'unassigns policy project and enqueues OrchestrationConfigurationRemoveBotForNamespaceWorker',
+        it 'does not unassign the policy project and enqueues OrchestrationConfigurationRemoveBotForNamespaceWorker',
           :aggregate_failures do
           expect(Security::OrchestrationConfigurationRemoveBotForNamespaceWorker).to receive(:perform_async).with(
             container.id, current_user.id)
 
           expect(result).to be_success
+
           exists = Security::OrchestrationPolicyConfiguration.exists?(
             container.security_orchestration_policy_configuration.id)
-          expect(exists).to be(false)
+          expect(exists).to be(true)
         end
       end
-
-      it_behaves_like 'unassigns policy project'
     end
   end
 end
diff --git a/ee/spec/support/shared_examples/workers/security/orchestration_configuration_bot_management_for_namespace_shared_examples.rb b/ee/spec/support/shared_examples/workers/security/orchestration_configuration_bot_management_for_namespace_shared_examples.rb
new file mode 100644
index 0000000000000000000000000000000000000000..3faab12962a0eb9c7dde71e3a71034db3e6dff79
--- /dev/null
+++ b/ee/spec/support/shared_examples/workers/security/orchestration_configuration_bot_management_for_namespace_shared_examples.rb
@@ -0,0 +1,64 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'bot management worker examples' do
+  describe '#perform' do
+    let_it_be(:namespace, reload: true) { create(:group, :with_security_orchestration_policy_configuration) }
+    let_it_be(:namespace_projects) { create_list(:project, 2, group: namespace) }
+    let_it_be(:user) { create(:user) }
+    let(:current_user_id) { nil }
+    let(:namespace_project_ids) { namespace_projects.map(&:id) }
+
+    subject(:run_worker) { described_class.new.perform(namespace_id, current_user_id) }
+
+    before_all do
+      namespace_projects.each do |project|
+        project.add_owner(user)
+      end
+    end
+
+    shared_examples_for 'worker exits without error' do
+      it 'does not enqueues additional workers' do
+        expect(management_worker).not_to receive(:bulk_perform_in_with_contexts)
+
+        run_worker
+      end
+
+      it 'exits without error' do
+        expect { run_worker }.not_to raise_error
+      end
+    end
+
+    context 'with invalid namespace_id' do
+      let(:namespace_id) { non_existing_record_id }
+
+      it_behaves_like 'worker exits without error'
+    end
+
+    context 'with valid project_id' do
+      let(:namespace_id) { namespace.id }
+
+      context 'when user with given current_user_id does not exist' do
+        let(:current_user_id) { non_existing_record_id }
+
+        it_behaves_like 'worker exits without error'
+      end
+
+      context 'when current user is provided' do
+        let(:current_user_id) { user.id }
+
+        it 'enqueues a worker for each projects', :aggregate_failures do
+          expect(management_worker)
+            .to receive(:bulk_perform_in_with_contexts)
+                  .with(kind_of(Integer), namespace_project_ids,
+                    { arguments_proc: kind_of(Proc), context_proc: kind_of(Proc) })
+
+          run_worker
+        end
+
+        it_behaves_like 'an idempotent worker' do
+          let(:job_args) { [namespace_id, current_user_id] }
+        end
+      end
+    end
+  end
+end
diff --git a/ee/spec/workers/security/orchestration_configuration_create_bot_for_namespace_worker_spec.rb b/ee/spec/workers/security/orchestration_configuration_create_bot_for_namespace_worker_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..acfad466524a475f68ce232d5c1ebd0f295672fa
--- /dev/null
+++ b/ee/spec/workers/security/orchestration_configuration_create_bot_for_namespace_worker_spec.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Security::OrchestrationConfigurationCreateBotForNamespaceWorker, feature_category: :security_policy_management do
+  let(:management_worker) { Security::OrchestrationConfigurationCreateBotWorker }
+
+  it_behaves_like 'bot management worker examples'
+end
diff --git a/ee/spec/workers/security/orchestration_configuration_remove_bot_for_namespace_worker_spec.rb b/ee/spec/workers/security/orchestration_configuration_remove_bot_for_namespace_worker_spec.rb
index fafc30c70861ad318db0b84404359538b4e74af7..1c2775af73910861148e4036f32b20fdcda317cd 100644
--- a/ee/spec/workers/security/orchestration_configuration_remove_bot_for_namespace_worker_spec.rb
+++ b/ee/spec/workers/security/orchestration_configuration_remove_bot_for_namespace_worker_spec.rb
@@ -3,62 +3,26 @@
 require 'spec_helper'
 
 RSpec.describe Security::OrchestrationConfigurationRemoveBotForNamespaceWorker, feature_category: :security_policy_management do
-  describe '#perform' do
-    let_it_be(:namespace, reload: true) { create(:group, :with_security_orchestration_policy_configuration) }
-    let_it_be(:namespace_projects) { create_list(:project, 2, group: namespace) }
-    let_it_be(:user) { create(:user) }
-    let(:current_user_id) { nil }
-    let(:namespace_project_ids) { namespace_projects.map(&:id) }
+  let(:management_worker) { Security::OrchestrationConfigurationRemoveBotWorker }
 
-    subject(:run_worker) { described_class.new.perform(namespace_id, current_user_id) }
-
-    before_all do
-      namespace_projects.each do |project|
-        project.add_owner(user)
-      end
-    end
-
-    shared_examples_for 'worker exits without error' do
-      it 'does not enqueues the Security::OrchestrationConfigurationRemoveBotWorker' do
-        expect(Security::OrchestrationConfigurationRemoveBotWorker).not_to receive(:bulk_perform_in_with_contexts)
-
-        run_worker
-      end
-
-      it 'exits without error' do
-        expect { run_worker }.not_to raise_error
-      end
-    end
-
-    context 'with invalid namespace_id' do
-      let(:namespace_id) { non_existing_record_id }
-
-      it_behaves_like 'worker exits without error'
-    end
+  it_behaves_like 'bot management worker examples'
 
+  describe 'delete_configuration' do
     context 'with valid project_id' do
+      let_it_be(:namespace, reload: true) { create(:group, :with_security_orchestration_policy_configuration) }
       let(:namespace_id) { namespace.id }
 
-      context 'when user with given current_user_id does not exist' do
-        let(:current_user_id) { non_existing_record_id }
-
-        it_behaves_like 'worker exits without error'
-      end
-
       context 'when current user is provided' do
-        let(:current_user_id) { user.id }
+        let_it_be(:current_user) { create(:user) }
+        let(:current_user_id) { current_user.id }
 
-        it 'enqueues the OrchestrationConfigurationRemoveBotWorker for all projects', :aggregate_failures do
-          expect(Security::OrchestrationConfigurationRemoveBotWorker)
-            .to receive(:bulk_perform_in_with_contexts)
-            .with(kind_of(Integer), namespace_project_ids,
-              { arguments_proc: kind_of(Proc), context_proc: kind_of(Proc) })
+        let(:policy_configuration) { namespace.security_orchestration_policy_configuration }
 
-          run_worker
-        end
+        it 'enqueues for deletion' do
+          expect(Security::DeleteOrchestrationConfigurationWorker).to receive(:perform_async).with(
+            policy_configuration.id, current_user_id, policy_configuration.security_policy_management_project.id)
 
-        it_behaves_like 'an idempotent worker' do
-          let(:job_args) { [namespace_id, current_user_id] }
+          described_class.new.perform(namespace_id, current_user_id)
         end
       end
     end
diff --git a/ee/spec/workers/security/unassign_redundant_policy_configurations_worker_spec.rb b/ee/spec/workers/security/unassign_redundant_policy_configurations_worker_spec.rb
index c5d936b9f5f5f4ad058cae4bb12d1d5c20c80195..08c675cd9bdf73b1a8967908f7d40e05e6da9d06 100644
--- a/ee/spec/workers/security/unassign_redundant_policy_configurations_worker_spec.rb
+++ b/ee/spec/workers/security/unassign_redundant_policy_configurations_worker_spec.rb
@@ -50,28 +50,46 @@
       create(:project_member, user: security_policy_bot, project: project)
     end
 
-    it 'does not unassign top-level group' do
-      expect { execute }.not_to change {
-        Security::OrchestrationPolicyConfiguration.exists?(policy_configuration_a.id)
-      }.from(true)
-    end
+    context 'when the `security_policy_bot_worker` feature flag is disabled' do
+      before do
+        stub_feature_flags(security_policy_bot_worker: false)
+      end
 
-    it 'unassigns projects and groups with redundant policy projects' do
-      execute
+      it 'does not unassign top-level group' do
+        expect { execute }.not_to change {
+          Security::OrchestrationPolicyConfiguration.exists?(policy_configuration_a.id)
+        }.from(true)
+      end
+
+      it 'unassigns projects and groups with redundant policy projects' do
+        execute
 
-      [policy_configuration_b, policy_configuration_c].each do |config|
-        expect(Security::OrchestrationPolicyConfiguration.exists?(config.id)).to be(false)
+        [policy_configuration_b, policy_configuration_c].each do |config|
+          expect(Security::OrchestrationPolicyConfiguration.exists?(config.id)).to be(false)
+        end
       end
-    end
 
-    it 'does not unassign unrelated projects' do
-      expect { execute }.not_to change {
-        Security::OrchestrationPolicyConfiguration.exists?(other_policy_configuration.id)
-      }.from(true)
+      it 'does not unassign unrelated projects' do
+        expect { execute }.not_to change {
+          Security::OrchestrationPolicyConfiguration.exists?(other_policy_configuration.id)
+        }.from(true)
+      end
+
+      it 'keeps bot users' do
+        expect { execute }.not_to change { project.security_policy_bot }.from(security_policy_bot)
+      end
     end
 
-    it 'keeps bot users' do
-      expect { execute }.not_to change { project.security_policy_bot }.from(security_policy_bot)
+    it 'delegates the unassign to Security::Orchestration::UnassignService' do
+      [subgroup_b, project].each do |container|
+        expect_next_instance_of(::Security::Orchestration::UnassignService,
+          container: container,
+          current_user: user) do |service|
+          expect(service).to receive(:execute).with(delete_bot: false).once.and_call_original
+        end
+      end
+
+      execute
     end
   end