diff --git a/db/post_migrate/20220920124709_backfill_internal_on_notes.rb b/db/post_migrate/20220920124709_backfill_internal_on_notes.rb
new file mode 100644
index 0000000000000000000000000000000000000000..0d7371959073640fe2c9ddb9a9e33754538f6316
--- /dev/null
+++ b/db/post_migrate/20220920124709_backfill_internal_on_notes.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+class BackfillInternalOnNotes < Gitlab::Database::Migration[2.0]
+  MIGRATION = 'BackfillInternalOnNotes'
+  DELAY_INTERVAL = 2.minutes
+  TABLE = :notes
+  BATCH_SIZE = 2000
+  SUB_BATCH_SIZE = 10
+
+  restrict_gitlab_migration gitlab_schema: :gitlab_main
+
+  def up
+    queue_batched_background_migration(
+      MIGRATION,
+      TABLE,
+      :id,
+      job_interval: DELAY_INTERVAL,
+      batch_size: BATCH_SIZE,
+      sub_batch_size: SUB_BATCH_SIZE
+    )
+  end
+
+  def down
+    delete_batched_background_migration(MIGRATION, TABLE, :id, [])
+  end
+end
diff --git a/db/schema_migrations/20220920124709 b/db/schema_migrations/20220920124709
new file mode 100644
index 0000000000000000000000000000000000000000..e3b015d44a7f67d04e95b51ca4326cb493f2cd66
--- /dev/null
+++ b/db/schema_migrations/20220920124709
@@ -0,0 +1 @@
+4a975867dc0539049902229521b4d94f940817ffd9196810856c8eb962c57e62
\ No newline at end of file
diff --git a/lib/gitlab/background_migration/backfill_internal_on_notes.rb b/lib/gitlab/background_migration/backfill_internal_on_notes.rb
new file mode 100644
index 0000000000000000000000000000000000000000..300f2cff6ca1e5095a602ecab7bc1472a0800359
--- /dev/null
+++ b/lib/gitlab/background_migration/backfill_internal_on_notes.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+module Gitlab
+  module BackgroundMigration
+    # This syncs the data to `internal` from `confidential` as we rename the column.
+    class BackfillInternalOnNotes < BatchedMigrationJob
+      scope_to -> (relation) { relation.where(confidential: true) }
+
+      def perform
+        each_sub_batch(operation_name: :update_all) do |sub_batch|
+          sub_batch.update_all(internal: true)
+        end
+      end
+    end
+  end
+end
diff --git a/spec/lib/gitlab/background_migration/backfill_internal_on_notes_spec.rb b/spec/lib/gitlab/background_migration/backfill_internal_on_notes_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..40a4758ba5f70958de9c5ee85365035146531ea5
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/backfill_internal_on_notes_spec.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::BackgroundMigration::BackfillInternalOnNotes, :migration, schema: 20220920124709 do
+  let(:notes_table) { table(:notes) }
+
+  let!(:confidential_note) { notes_table.create!(id: 1, confidential: true, internal: false) }
+  let!(:non_confidential_note) { notes_table.create!(id: 2, confidential: false, internal: false) }
+
+  describe '#perform' do
+    subject(:perform) do
+      described_class.new(
+        start_id: 1,
+        end_id: 2,
+        batch_table: :notes,
+        batch_column: :id,
+        sub_batch_size: 1,
+        pause_ms: 0,
+        connection: ApplicationRecord.connection
+      ).perform
+    end
+
+    it 'backfills internal column on notes when confidential' do
+      expect { perform }
+        .to change { confidential_note.reload.internal }.from(false).to(true)
+        .and not_change { non_confidential_note.reload.internal }
+    end
+  end
+end
diff --git a/spec/migrations/20220920124709_backfill_internal_on_notes_spec.rb b/spec/migrations/20220920124709_backfill_internal_on_notes_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..f4ac6e6fc8e5bddddbfd0117c5f781992c752638
--- /dev/null
+++ b/spec/migrations/20220920124709_backfill_internal_on_notes_spec.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!
+
+RSpec.describe BackfillInternalOnNotes, :migration do
+  let(:migration) { described_class::MIGRATION }
+
+  describe '#up' do
+    it 'schedules background jobs for each batch of issues' do
+      migrate!
+
+      expect(migration).to have_scheduled_batched_migration(
+        table_name: :notes,
+        column_name: :id,
+        interval: described_class::DELAY_INTERVAL,
+        batch_size: described_class::BATCH_SIZE,
+        sub_batch_size: described_class::SUB_BATCH_SIZE
+      )
+    end
+  end
+
+  describe '#down' do
+    it 'deletes all batched migration records' do
+      migrate!
+      schema_migrate_down!
+
+      expect(migration).not_to have_scheduled_batched_migration
+    end
+  end
+end