diff --git a/config/sidekiq_queues.yml b/config/sidekiq_queues.yml
index 2e5fa7923b32e4cdba197f31240300862dbc3c3a..f5c1379591acbb9a7da3f658d57006b6650ee27d 100644
--- a/config/sidekiq_queues.yml
+++ b/config/sidekiq_queues.yml
@@ -659,6 +659,8 @@
   - 1
 - - sbom_reports
   - 1
+- - sbom_sync_archived_status
+  - 1
 - - sbom_sync_project_traversal_ids
   - 1
 - - search_elastic_default_branch_changed
diff --git a/ee/app/services/sbom/sync_archived_status_service.rb b/ee/app/services/sbom/sync_archived_status_service.rb
new file mode 100644
index 0000000000000000000000000000000000000000..2ee021a6b92ef99418031182b6c6a4b9ba091b23
--- /dev/null
+++ b/ee/app/services/sbom/sync_archived_status_service.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+module Sbom
+  class SyncArchivedStatusService
+    include Gitlab::Utils::StrongMemoize
+    include Gitlab::ExclusiveLeaseHelpers
+
+    BATCH_SIZE = 100
+    LEASE_TTL = 1.hour
+
+    def initialize(project_id)
+      @project_id = project_id
+    end
+
+    def execute
+      return unless project
+
+      in_lock(lease_key, ttl: LEASE_TTL) { update_archived_status }
+    end
+
+    private
+
+    attr_reader :project_id
+
+    def update_archived_status
+      project.sbom_occurrences.each_batch(of: BATCH_SIZE) do |batch|
+        batch.update_all(archived: project.archived)
+      end
+    end
+
+    def project
+      Project.find_by_id(project_id)
+    end
+    strong_memoize_attr :project
+
+    def lease_key
+      "sync_sbom_occurrences_archived:projects:#{project_id}"
+    end
+  end
+end
diff --git a/ee/app/workers/all_queues.yml b/ee/app/workers/all_queues.yml
index 750f9c80ffcc5a5e18885b65e8329da2f4764f6c..bc4e81c67154da1d2b00dab8d1371c8168d4cd54 100644
--- a/ee/app/workers/all_queues.yml
+++ b/ee/app/workers/all_queues.yml
@@ -1821,6 +1821,15 @@
   :weight: 1
   :idempotent: true
   :tags: []
+- :name: sbom_sync_archived_status
+  :worker_name: Sbom::SyncArchivedStatusWorker
+  :feature_category: :dependency_management
+  :has_external_dependencies: false
+  :urgency: :low
+  :resource_boundary: :unknown
+  :weight: 1
+  :idempotent: true
+  :tags: []
 - :name: sbom_sync_project_traversal_ids
   :worker_name: Sbom::SyncProjectTraversalIdsWorker
   :feature_category: :dependency_management
diff --git a/ee/app/workers/sbom/sync_archived_status_worker.rb b/ee/app/workers/sbom/sync_archived_status_worker.rb
new file mode 100644
index 0000000000000000000000000000000000000000..ae42f83eabf36e60497cdc042b4182f7ff132244
--- /dev/null
+++ b/ee/app/workers/sbom/sync_archived_status_worker.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module Sbom
+  class SyncArchivedStatusWorker
+    include Gitlab::EventStore::Subscriber
+
+    data_consistency :always
+    feature_category :dependency_management
+    idempotent!
+
+    def handle_event(event)
+      ::Sbom::SyncArchivedStatusService.new(event.data['project_id']).execute
+    end
+  end
+end
diff --git a/ee/config/feature_flags/gitlab_com_derisk/sync_project_archival_status_to_sbom_occurrences.yml b/ee/config/feature_flags/gitlab_com_derisk/sync_project_archival_status_to_sbom_occurrences.yml
new file mode 100644
index 0000000000000000000000000000000000000000..f7d15342a58120e080419406f4bc0ea12e1249f2
--- /dev/null
+++ b/ee/config/feature_flags/gitlab_com_derisk/sync_project_archival_status_to_sbom_occurrences.yml
@@ -0,0 +1,9 @@
+---
+name: sync_project_archival_status_to_sbom_occurrences
+feature_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/437636
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/143874
+rollout_issue_url: https://gitlab.com/gitlab-com/gl-infra/production/-/issues/17572
+milestone: '16.10'
+group: group::threat insights
+type: gitlab_com_derisk
+default_enabled: false
diff --git a/ee/lib/ee/gitlab/event_store.rb b/ee/lib/ee/gitlab/event_store.rb
index 1a9c42f4a2c54343f85e58365d1df95314c9dfbf..c38633214907a751c6d34c0afb2ca4bd45c7b753 100644
--- a/ee/lib/ee/gitlab/event_store.rb
+++ b/ee/lib/ee/gitlab/event_store.rb
@@ -63,6 +63,11 @@ def configure!(store)
                   ::Feature.enabled?(:update_vuln_reads_traversal_ids_via_event,
                     ::Group.find_by_id(event.data['group_id']), type: :gitlab_com_derisk)
                 }
+          store.subscribe ::Sbom::SyncArchivedStatusWorker, to: ::Projects::ProjectArchivedEvent,
+            if: ->(event) do
+              project = ::Project.find_by_id(event.data['project_id'])
+              ::Feature.enabled?(:sync_project_archival_status_to_sbom_occurrences, project)
+            end
         end
       end
     end
diff --git a/ee/spec/services/sbom/sync_archived_status_service_spec.rb b/ee/spec/services/sbom/sync_archived_status_service_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..b26f5228e5397bc3c6463e010eca8d4eaa27eadb
--- /dev/null
+++ b/ee/spec/services/sbom/sync_archived_status_service_spec.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Sbom::SyncArchivedStatusService, feature_category: :dependency_management do
+  let_it_be(:project) { create(:project, :archived) }
+  let_it_be(:sbom_occurrence) { create(:sbom_occurrence, project: project) }
+  let_it_be(:sbom_occurrence_2) { create(:sbom_occurrence, project: project) }
+
+  let(:project_id) { project.id }
+
+  subject(:sync) { described_class.new(project_id).execute }
+
+  it 'updates sbom_occurrences.archived' do
+    expect { sync }.to change { sbom_occurrence.reload.archived }.from(false).to(true)
+  end
+
+  context 'when project does not exist with id' do
+    let(:project_id) { non_existing_record_id }
+
+    it 'does not raise' do
+      expect { sync }.not_to raise_error
+    end
+  end
+
+  context 'when lease is taken' do
+    include ExclusiveLeaseHelpers
+
+    let_it_be(:other_project) { create(:project) }
+
+    let(:lease_key) { "sync_sbom_occurrences_archived:projects:#{project_id}" }
+    let(:lease_ttl) { 1.hour }
+
+    before do
+      stub_exclusive_lease_taken(lease_key, timeout: lease_ttl)
+    end
+
+    it 'does not permit parallel execution on the same project' do
+      expect { sync }.to raise_error(Gitlab::ExclusiveLeaseHelpers::FailedToObtainLockError)
+                          .and not_change { sbom_occurrence.reload.archived }
+    end
+
+    it 'allows parallel execution on different projects' do
+      expect { described_class.new(other_project.id).execute }.not_to raise_error
+    end
+  end
+end
diff --git a/ee/spec/workers/sbom/sync_archived_status_worker_spec.rb b/ee/spec/workers/sbom/sync_archived_status_worker_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..758ebda1b5eb4f7ab6f1a5ff3f9d7f6bf773e704
--- /dev/null
+++ b/ee/spec/workers/sbom/sync_archived_status_worker_spec.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Sbom::SyncArchivedStatusWorker, feature_category: :dependency_management, type: :worker do
+  let_it_be(:project) { create(:project) }
+  let_it_be(:sbom_occurrence) { create(:sbom_occurrence, project: project) }
+  let_it_be(:sbom_occurrence_outside_project) { create(:sbom_occurrence) }
+
+  let(:event) do
+    ::Projects::ProjectArchivedEvent.new(data: {
+      project_id: project.id,
+      namespace_id: project.namespace.id,
+      root_namespace_id: project.root_namespace.id
+    })
+  end
+
+  it_behaves_like 'worker with data consistency', described_class, data_consistency: :always
+  it_behaves_like 'subscribes to event'
+
+  subject(:use_event) { consume_event(subscriber: described_class, event: event) }
+
+  it 'updates sbom_occurrences archived status' do
+    project.update!(archived: true)
+
+    expect { use_event }.to change { sbom_occurrence.reload.archived }.from(false).to(true)
+      .and not_change { sbom_occurrence_outside_project.reload.archived }
+  end
+
+  context 'when sync_project_archival_status_to_sbom_occurrences is disabled' do
+    before do
+      stub_feature_flags(sync_project_archival_status_to_sbom_occurrences: false)
+    end
+
+    it_behaves_like 'ignores the published event'
+  end
+end