diff --git a/db/docs/batched_background_migrations/backfill_incident_management_pending_alert_escalations_project_id.yml b/db/docs/batched_background_migrations/backfill_incident_management_pending_alert_escalations_project_id.yml
new file mode 100644
index 0000000000000000000000000000000000000000..a5c9fd604eb88f34ae44e7f49eb3ed0d846ce20e
--- /dev/null
+++ b/db/docs/batched_background_migrations/backfill_incident_management_pending_alert_escalations_project_id.yml
@@ -0,0 +1,9 @@
+---
+migration_job_name: BackfillIncidentManagementPendingAlertEscalationsProjectId
+description: Backfills sharding key `incident_management_pending_alert_escalations.project_id` from `alert_management_alerts`.
+feature_category: incident_management
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/166816
+milestone: '17.5'
+queued_migration_version: 20240922141648
+finalize_after: '2024-10-22'
+finalized_by: # version of the migration that finalized this BBM
diff --git a/db/docs/incident_management_pending_alert_escalations.yml b/db/docs/incident_management_pending_alert_escalations.yml
index 618761b10d2115ac537db205cef08979526845f1..624a0cde611fb6077c5b848f73f9dd794360b005 100644
--- a/db/docs/incident_management_pending_alert_escalations.yml
+++ b/db/docs/incident_management_pending_alert_escalations.yml
@@ -19,3 +19,4 @@ desired_sharding_key:
         table: alert_management_alerts
         sharding_key: project_id
         belongs_to: alert
+desired_sharding_key_migration_job_name: BackfillIncidentManagementPendingAlertEscalationsProjectId
diff --git a/db/migrate/20240922141644_add_project_id_to_incident_management_pending_alert_escalations.rb b/db/migrate/20240922141644_add_project_id_to_incident_management_pending_alert_escalations.rb
new file mode 100644
index 0000000000000000000000000000000000000000..ce361bbae1c2b2cce135fbf561462f87e42142fa
--- /dev/null
+++ b/db/migrate/20240922141644_add_project_id_to_incident_management_pending_alert_escalations.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class AddProjectIdToIncidentManagementPendingAlertEscalations < Gitlab::Database::Migration[2.2]
+  milestone '17.5'
+
+  def change
+    add_column :incident_management_pending_alert_escalations, :project_id, :bigint
+  end
+end
diff --git a/db/post_migrate/20240922141645_index_incident_management_pending_alert_escalations_on_project_id.rb b/db/post_migrate/20240922141645_index_incident_management_pending_alert_escalations_on_project_id.rb
new file mode 100644
index 0000000000000000000000000000000000000000..7046378655e6ac533433879d2efdc7ec31546d9a
--- /dev/null
+++ b/db/post_migrate/20240922141645_index_incident_management_pending_alert_escalations_on_project_id.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class IndexIncidentManagementPendingAlertEscalationsOnProjectId < Gitlab::Database::Migration[2.2]
+  include Gitlab::Database::PartitioningMigrationHelpers
+
+  milestone '17.5'
+  disable_ddl_transaction!
+
+  INDEX_NAME = 'idx_incident_management_pending_alert_escalations_on_project_id'
+
+  def up
+    add_concurrent_partitioned_index :incident_management_pending_alert_escalations, :project_id, name: INDEX_NAME
+  end
+
+  def down
+    remove_concurrent_partitioned_index_by_name :incident_management_pending_alert_escalations, INDEX_NAME
+  end
+end
diff --git a/db/post_migrate/20240922141646_add_incident_management_pending_alert_escalations_project_id_fk.rb b/db/post_migrate/20240922141646_add_incident_management_pending_alert_escalations_project_id_fk.rb
new file mode 100644
index 0000000000000000000000000000000000000000..d24c3856a2182f3a7570ae5cf95902859c0b4803
--- /dev/null
+++ b/db/post_migrate/20240922141646_add_incident_management_pending_alert_escalations_project_id_fk.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class AddIncidentManagementPendingAlertEscalationsProjectIdFk < Gitlab::Database::Migration[2.2]
+  include Gitlab::Database::PartitioningMigrationHelpers
+
+  milestone '17.5'
+  disable_ddl_transaction!
+
+  def up
+    add_concurrent_partitioned_foreign_key :incident_management_pending_alert_escalations, :projects,
+      column: :project_id, on_delete: :cascade
+  end
+
+  def down
+    with_lock_retries do
+      remove_foreign_key :incident_management_pending_alert_escalations, column: :project_id
+    end
+  end
+end
diff --git a/db/post_migrate/20240922141647_add_incident_management_pending_alert_escalations_project_id_trigger.rb b/db/post_migrate/20240922141647_add_incident_management_pending_alert_escalations_project_id_trigger.rb
new file mode 100644
index 0000000000000000000000000000000000000000..4c0b357d0d409d61c5a3ed9a117a84e26d409c1a
--- /dev/null
+++ b/db/post_migrate/20240922141647_add_incident_management_pending_alert_escalations_project_id_trigger.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+class AddIncidentManagementPendingAlertEscalationsProjectIdTrigger < Gitlab::Database::Migration[2.2]
+  milestone '17.5'
+
+  def up
+    install_sharding_key_assignment_trigger(
+      table: :incident_management_pending_alert_escalations,
+      sharding_key: :project_id,
+      parent_table: :alert_management_alerts,
+      parent_sharding_key: :project_id,
+      foreign_key: :alert_id
+    )
+  end
+
+  def down
+    remove_sharding_key_assignment_trigger(
+      table: :incident_management_pending_alert_escalations,
+      sharding_key: :project_id,
+      parent_table: :alert_management_alerts,
+      parent_sharding_key: :project_id,
+      foreign_key: :alert_id
+    )
+  end
+end
diff --git a/db/post_migrate/20240922141648_queue_backfill_incident_management_pending_alert_escalations_project_id.rb b/db/post_migrate/20240922141648_queue_backfill_incident_management_pending_alert_escalations_project_id.rb
new file mode 100644
index 0000000000000000000000000000000000000000..25cc40b49a8a46cfb09c5cbb4e635e9e81223553
--- /dev/null
+++ b/db/post_migrate/20240922141648_queue_backfill_incident_management_pending_alert_escalations_project_id.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+class QueueBackfillIncidentManagementPendingAlertEscalationsProjectId < Gitlab::Database::Migration[2.2]
+  milestone '17.5'
+  restrict_gitlab_migration gitlab_schema: :gitlab_main_cell
+
+  MIGRATION = "BackfillIncidentManagementPendingAlertEscalationsProjectId"
+  DELAY_INTERVAL = 2.minutes
+  BATCH_SIZE = 1000
+  SUB_BATCH_SIZE = 100
+
+  def up
+    queue_batched_background_migration(
+      MIGRATION,
+      :incident_management_pending_alert_escalations,
+      :id,
+      :project_id,
+      :alert_management_alerts,
+      :project_id,
+      :alert_id,
+      job_interval: DELAY_INTERVAL,
+      batch_size: BATCH_SIZE,
+      batch_class_name: 'LooseIndexScanBatchingStrategy',
+      sub_batch_size: SUB_BATCH_SIZE
+    )
+  end
+
+  def down
+    delete_batched_background_migration(
+      MIGRATION,
+      :incident_management_pending_alert_escalations,
+      :id,
+      [
+        :project_id,
+        :alert_management_alerts,
+        :project_id,
+        :alert_id
+      ]
+    )
+  end
+end
diff --git a/db/schema_migrations/20240922141644 b/db/schema_migrations/20240922141644
new file mode 100644
index 0000000000000000000000000000000000000000..140b2cbd1246a76ad75b1342696b96f107c5ac5a
--- /dev/null
+++ b/db/schema_migrations/20240922141644
@@ -0,0 +1 @@
+b8c02e88adae3597a42e8ecd94beabad3b6265c62957d587dcce8f689322e404
\ No newline at end of file
diff --git a/db/schema_migrations/20240922141645 b/db/schema_migrations/20240922141645
new file mode 100644
index 0000000000000000000000000000000000000000..b4a32747be406b621d2f2b76b551222a76c8b6c6
--- /dev/null
+++ b/db/schema_migrations/20240922141645
@@ -0,0 +1 @@
+5c8fda84cba2c51cadd8c0abc6412dc05d865cef7af202f203d2ae9ea7cd6776
\ No newline at end of file
diff --git a/db/schema_migrations/20240922141646 b/db/schema_migrations/20240922141646
new file mode 100644
index 0000000000000000000000000000000000000000..fb949f170bb6c0467b40d57ff4c4ea8a061fdc54
--- /dev/null
+++ b/db/schema_migrations/20240922141646
@@ -0,0 +1 @@
+f644c263e308a51a29ca9e185badb42ae6a1141ed130366fabe516b36b953777
\ No newline at end of file
diff --git a/db/schema_migrations/20240922141647 b/db/schema_migrations/20240922141647
new file mode 100644
index 0000000000000000000000000000000000000000..01d50ce1f2e397782b16e8901bba1e20774891b3
--- /dev/null
+++ b/db/schema_migrations/20240922141647
@@ -0,0 +1 @@
+e09a4a341028bf25277a5c4f09b242a59e91dd57ba77f15fc7110790cf76737e
\ No newline at end of file
diff --git a/db/schema_migrations/20240922141648 b/db/schema_migrations/20240922141648
new file mode 100644
index 0000000000000000000000000000000000000000..cea06ca065e03ea5dc0b380672d7e4705bcd983e
--- /dev/null
+++ b/db/schema_migrations/20240922141648
@@ -0,0 +1 @@
+2d37d86d200cbd0ac22c6d463346086b34bfe148cfadac0eb0905091fb4cb4a9
\ No newline at end of file
diff --git a/db/structure.sql b/db/structure.sql
index a6add27da228539d7c6d055aeda8e4152ceee1cf..1161adad1f296b3198d4b5db7ec4f8a9532259b3 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -1081,6 +1081,22 @@ RETURN NEW;
 END
 $$;
 
+CREATE FUNCTION trigger_2a994bb5629f() RETURNS trigger
+    LANGUAGE plpgsql
+    AS $$
+BEGIN
+IF NEW."project_id" IS NULL THEN
+  SELECT "project_id"
+  INTO NEW."project_id"
+  FROM "alert_management_alerts"
+  WHERE "alert_management_alerts"."id" = NEW."alert_id";
+END IF;
+
+RETURN NEW;
+
+END
+$$;
+
 CREATE FUNCTION trigger_2b8fdc9b4a4e() RETURNS trigger
     LANGUAGE plpgsql
     AS $$
@@ -2805,7 +2821,8 @@ CREATE TABLE incident_management_pending_alert_escalations (
     alert_id bigint NOT NULL,
     process_at timestamp with time zone NOT NULL,
     created_at timestamp with time zone NOT NULL,
-    updated_at timestamp with time zone NOT NULL
+    updated_at timestamp with time zone NOT NULL,
+    project_id bigint
 )
 PARTITION BY RANGE (process_at);
 
@@ -27004,6 +27021,8 @@ CREATE INDEX idx_import_placeholder_memberships_on_source_user_id_and_id ON impo
 
 CREATE UNIQUE INDEX idx_import_placeholder_memberships_on_source_user_project_id ON import_placeholder_memberships USING btree (source_user_id, project_id);
 
+CREATE INDEX idx_incident_management_pending_alert_escalations_on_project_id ON ONLY incident_management_pending_alert_escalations USING btree (project_id);
+
 CREATE INDEX idx_incident_management_timeline_event_tag_links_on_project_id ON incident_management_timeline_event_tag_links USING btree (project_id);
 
 CREATE INDEX idx_installable_conan_pkgs_on_project_id_id ON packages_packages USING btree (project_id, id) WHERE ((package_type = 3) AND (status = ANY (ARRAY[0, 1])));
@@ -33280,6 +33299,8 @@ CREATE TRIGGER trigger_25d35f02ab55 BEFORE INSERT OR UPDATE ON ml_candidate_meta
 
 CREATE TRIGGER trigger_25fe4f7da510 BEFORE INSERT OR UPDATE ON vulnerability_issue_links FOR EACH ROW EXECUTE FUNCTION trigger_25fe4f7da510();
 
+CREATE TRIGGER trigger_2a994bb5629f BEFORE INSERT OR UPDATE ON incident_management_pending_alert_escalations FOR EACH ROW EXECUTE FUNCTION trigger_2a994bb5629f();
+
 CREATE TRIGGER trigger_2b8fdc9b4a4e BEFORE INSERT OR UPDATE ON ml_experiment_metadata FOR EACH ROW EXECUTE FUNCTION trigger_2b8fdc9b4a4e();
 
 CREATE TRIGGER trigger_30209d0fba3e BEFORE INSERT OR UPDATE ON alert_management_alert_user_mentions FOR EACH ROW EXECUTE FUNCTION trigger_30209d0fba3e();
@@ -35375,6 +35396,9 @@ ALTER TABLE ONLY group_group_links
 ALTER TABLE ONLY packages_debian_group_component_files
     ADD CONSTRAINT fk_rails_2b8992dd83 FOREIGN KEY (architecture_id) REFERENCES packages_debian_group_architectures(id) ON DELETE RESTRICT;
 
+ALTER TABLE incident_management_pending_alert_escalations
+    ADD CONSTRAINT fk_rails_2bbafb00ef FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+
 ALTER TABLE ONLY boards_epic_board_labels
     ADD CONSTRAINT fk_rails_2bedeb8799 FOREIGN KEY (label_id) REFERENCES labels(id) ON DELETE CASCADE;
 
diff --git a/lib/gitlab/background_migration/backfill_incident_management_pending_alert_escalations_project_id.rb b/lib/gitlab/background_migration/backfill_incident_management_pending_alert_escalations_project_id.rb
new file mode 100644
index 0000000000000000000000000000000000000000..b884fe98d63e4bf9061d2f34376a2e661be1d7c5
--- /dev/null
+++ b/lib/gitlab/background_migration/backfill_incident_management_pending_alert_escalations_project_id.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+module Gitlab
+  module BackgroundMigration
+    class BackfillIncidentManagementPendingAlertEscalationsProjectId < BackfillDesiredShardingKeyJob
+      operation_name :backfill_incident_management_pending_alert_escalations_project_id
+      feature_category :incident_management
+    end
+  end
+end
diff --git a/spec/lib/gitlab/background_migration/backfill_incident_management_pending_alert_escalations_project_id_spec.rb b/spec/lib/gitlab/background_migration/backfill_incident_management_pending_alert_escalations_project_id_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..4a5c32f85f58cf9604051973a0e8a42e3602fbfe
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/backfill_incident_management_pending_alert_escalations_project_id_spec.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::BackgroundMigration::BackfillIncidentManagementPendingAlertEscalationsProjectId,
+  feature_category: :incident_management,
+  schema: 20240922141644 do
+  include_examples 'desired sharding key backfill job' do
+    let(:batch_table) { :incident_management_pending_alert_escalations }
+    let(:backfill_column) { :project_id }
+    let(:backfill_via_table) { :alert_management_alerts }
+    let(:backfill_via_column) { :project_id }
+    let(:backfill_via_foreign_key) { :alert_id }
+  end
+end
diff --git a/spec/migrations/20240922141648_queue_backfill_incident_management_pending_alert_escalations_project_id_spec.rb b/spec/migrations/20240922141648_queue_backfill_incident_management_pending_alert_escalations_project_id_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..ba9f8f19683e7046d95eac5e2aae07f536e01410
--- /dev/null
+++ b/spec/migrations/20240922141648_queue_backfill_incident_management_pending_alert_escalations_project_id_spec.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!
+
+RSpec.describe QueueBackfillIncidentManagementPendingAlertEscalationsProjectId, feature_category: :incident_management do
+  let!(:batched_migration) { described_class::MIGRATION }
+
+  it 'schedules a new batched migration' do
+    reversible_migration do |migration|
+      migration.before -> {
+        expect(batched_migration).not_to have_scheduled_batched_migration
+      }
+
+      migration.after -> {
+        expect(batched_migration).to have_scheduled_batched_migration(
+          table_name: :incident_management_pending_alert_escalations,
+          column_name: :id,
+          interval: described_class::DELAY_INTERVAL,
+          batch_size: described_class::BATCH_SIZE,
+          batch_class_name: 'LooseIndexScanBatchingStrategy',
+          sub_batch_size: described_class::SUB_BATCH_SIZE,
+          gitlab_schema: :gitlab_main_cell,
+          job_arguments: [
+            :project_id,
+            :alert_management_alerts,
+            :project_id,
+            :alert_id
+          ]
+        )
+      }
+    end
+  end
+end