diff --git a/db/post_migrate/20210727113447_backfill_integrations_type_new.rb b/db/post_migrate/20210727113447_backfill_integrations_type_new.rb
new file mode 100644
index 0000000000000000000000000000000000000000..8544c236fd7bf439ff072f809653c327d5c7214b
--- /dev/null
+++ b/db/post_migrate/20210727113447_backfill_integrations_type_new.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+class BackfillIntegrationsTypeNew < ActiveRecord::Migration[6.1]
+  include Gitlab::Database::MigrationHelpers
+
+  MIGRATION = 'BackfillIntegrationsTypeNew'
+  INTERVAL = 2.minutes
+
+  def up
+    queue_batched_background_migration(
+      MIGRATION,
+      :integrations,
+      :id,
+      job_interval: INTERVAL
+    )
+  end
+
+  def down
+    Gitlab::Database::BackgroundMigration::BatchedMigration
+      .for_configuration(MIGRATION, :integrations, :id, [])
+      .delete_all
+  end
+end
diff --git a/db/schema_migrations/20210727113447 b/db/schema_migrations/20210727113447
new file mode 100644
index 0000000000000000000000000000000000000000..236022f5af391320ac7ed9542f4690b7401e501d
--- /dev/null
+++ b/db/schema_migrations/20210727113447
@@ -0,0 +1 @@
+19e23131949e6056ea9837231fac6a2307fb52a8287eb34cc6e89eed11d52849
\ No newline at end of file
diff --git a/lib/gitlab/background_migration/backfill_integrations_type_new.rb b/lib/gitlab/background_migration/backfill_integrations_type_new.rb
new file mode 100644
index 0000000000000000000000000000000000000000..6a2d82aaeeebf7060bdce65480cf3d4a906555cd
--- /dev/null
+++ b/lib/gitlab/background_migration/backfill_integrations_type_new.rb
@@ -0,0 +1,62 @@
+# frozen_string_literal: true
+
+module Gitlab
+  module BackgroundMigration
+    # Backfills the new `integrations.type_new` column, which contains
+    # the real class name, rather than the legacy class name in `type`
+    # which is mapped via `Gitlab::Integrations::StiType`.
+    class BackfillIntegrationsTypeNew
+      def perform(start_id, stop_id, *args)
+        ActiveRecord::Base.connection.execute(<<~SQL)
+          WITH mapping(old_type, new_type) AS (VALUES
+            ('AsanaService',                   'Integrations::Asana'),
+            ('AssemblaService',                'Integrations::Assembla'),
+            ('BambooService',                  'Integrations::Bamboo'),
+            ('BugzillaService',                'Integrations::Bugzilla'),
+            ('BuildkiteService',               'Integrations::Buildkite'),
+            ('CampfireService',                'Integrations::Campfire'),
+            ('ConfluenceService',              'Integrations::Confluence'),
+            ('CustomIssueTrackerService',      'Integrations::CustomIssueTracker'),
+            ('DatadogService',                 'Integrations::Datadog'),
+            ('DiscordService',                 'Integrations::Discord'),
+            ('DroneCiService',                 'Integrations::DroneCi'),
+            ('EmailsOnPushService',            'Integrations::EmailsOnPush'),
+            ('EwmService',                     'Integrations::Ewm'),
+            ('ExternalWikiService',            'Integrations::ExternalWiki'),
+            ('FlowdockService',                'Integrations::Flowdock'),
+            ('HangoutsChatService',            'Integrations::HangoutsChat'),
+            ('IrkerService',                   'Integrations::Irker'),
+            ('JenkinsService',                 'Integrations::Jenkins'),
+            ('JiraService',                    'Integrations::Jira'),
+            ('MattermostService',              'Integrations::Mattermost'),
+            ('MattermostSlashCommandsService', 'Integrations::MattermostSlashCommands'),
+            ('MicrosoftTeamsService',          'Integrations::MicrosoftTeams'),
+            ('MockCiService',                  'Integrations::MockCi'),
+            ('MockMonitoringService',          'Integrations::MockMonitoring'),
+            ('PackagistService',               'Integrations::Packagist'),
+            ('PipelinesEmailService',          'Integrations::PipelinesEmail'),
+            ('PivotaltrackerService',          'Integrations::Pivotaltracker'),
+            ('PrometheusService',              'Integrations::Prometheus'),
+            ('PushoverService',                'Integrations::Pushover'),
+            ('RedmineService',                 'Integrations::Redmine'),
+            ('SlackService',                   'Integrations::Slack'),
+            ('SlackSlashCommandsService',      'Integrations::SlackSlashCommands'),
+            ('TeamcityService',                'Integrations::Teamcity'),
+            ('UnifyCircuitService',            'Integrations::UnifyCircuit'),
+            ('WebexTeamsService',              'Integrations::WebexTeams'),
+            ('YoutrackService',                'Integrations::Youtrack'),
+
+            -- EE-only integrations
+            ('GithubService',                  'Integrations::Github'),
+            ('GitlabSlackApplicationService',  'Integrations::GitlabSlackApplication')
+          )
+
+          UPDATE integrations SET type_new = mapping.new_type
+          FROM mapping
+          WHERE integrations.id BETWEEN #{start_id} AND #{stop_id}
+            AND integrations.type = mapping.old_type
+        SQL
+      end
+    end
+  end
+end
diff --git a/lib/gitlab/integrations/sti_type.rb b/lib/gitlab/integrations/sti_type.rb
index f7a0d115aee4651be557f67abf050647c04062c2..0fa9f435b5c68181eb32d126e1a53fa887622241 100644
--- a/lib/gitlab/integrations/sti_type.rb
+++ b/lib/gitlab/integrations/sti_type.rb
@@ -7,7 +7,7 @@ class StiType < ActiveRecord::Type::String
         Asana Assembla Bamboo Bugzilla Buildkite Campfire Confluence CustomIssueTracker Datadog
         Discord DroneCi EmailsOnPush Ewm ExternalWiki Flowdock HangoutsChat Irker Jenkins Jira Mattermost
         MattermostSlashCommands MicrosoftTeams MockCi MockMonitoring Packagist PipelinesEmail Pivotaltracker
-        Prometheus Pushover Redmine Slack SlackSlashCommands Teamcity UnifyCircuit Youtrack WebexTeams
+        Prometheus Pushover Redmine Slack SlackSlashCommands Teamcity UnifyCircuit WebexTeams Youtrack
       )).freeze
 
       def self.namespaced_integrations
diff --git a/spec/lib/gitlab/background_migration/backfill_integrations_type_new_spec.rb b/spec/lib/gitlab/background_migration/backfill_integrations_type_new_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..eaad5f8158b67d03fd79d50b80581cbab4ab2a32
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/backfill_integrations_type_new_spec.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::BackgroundMigration::BackfillIntegrationsTypeNew do
+  let(:integrations) { table(:integrations) }
+  let(:namespaced_integrations) { Gitlab::Integrations::StiType.namespaced_integrations }
+
+  before do
+    integrations.connection.execute 'ALTER TABLE integrations DISABLE TRIGGER "trigger_type_new_on_insert"'
+
+    namespaced_integrations.each_with_index do |type, i|
+      integrations.create!(id: i + 1, type: "#{type}Service")
+    end
+  ensure
+    integrations.connection.execute 'ALTER TABLE integrations ENABLE TRIGGER "trigger_type_new_on_insert"'
+  end
+
+  it 'backfills `type_new` for the selected records' do
+    described_class.new.perform(2, 10)
+
+    expect(integrations.where(id: 2..10).pluck(:type, :type_new)).to contain_exactly(
+      ['AssemblaService',           'Integrations::Assembla'],
+      ['BambooService',             'Integrations::Bamboo'],
+      ['BugzillaService',           'Integrations::Bugzilla'],
+      ['BuildkiteService',          'Integrations::Buildkite'],
+      ['CampfireService',           'Integrations::Campfire'],
+      ['ConfluenceService',         'Integrations::Confluence'],
+      ['CustomIssueTrackerService', 'Integrations::CustomIssueTracker'],
+      ['DatadogService',            'Integrations::Datadog'],
+      ['DiscordService',            'Integrations::Discord']
+    )
+
+    expect(integrations.where.not(id: 2..10)).to all(have_attributes(type_new: nil))
+  end
+end
diff --git a/spec/migrations/backfill_integrations_type_new_spec.rb b/spec/migrations/backfill_integrations_type_new_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..5b8fbf6f555da49d26b6f7224a5504978fc09c8c
--- /dev/null
+++ b/spec/migrations/backfill_integrations_type_new_spec.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!
+
+RSpec.describe BackfillIntegrationsTypeNew do
+  let_it_be(:migration) { described_class::MIGRATION }
+  let_it_be(:integrations) { table(:integrations) }
+
+  before do
+    integrations.create!(id: 1)
+    integrations.create!(id: 2)
+    integrations.create!(id: 3)
+    integrations.create!(id: 4)
+    integrations.create!(id: 5)
+  end
+
+  describe '#up' do
+    it 'schedules background jobs for each batch of integrations' do
+      migrate!
+
+      expect(migration).to have_scheduled_batched_migration(
+        table_name: :integrations,
+        column_name: :id,
+        interval: described_class::INTERVAL
+      )
+    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
diff --git a/spec/support/matchers/background_migrations_matchers.rb b/spec/support/matchers/background_migrations_matchers.rb
index 08bbbcc74382bd9bd8647a1b02ec7662f7c2c8d0..d3833a1e8e8ca746bc903937d4fed909f3cd4237 100644
--- a/spec/support/matchers/background_migrations_matchers.rb
+++ b/spec/support/matchers/background_migrations_matchers.rb
@@ -64,3 +64,33 @@ def same_arrays?(arg, expected)
     arg.sort == expected.sort
   end
 end
+
+RSpec::Matchers.define :have_scheduled_batched_migration do |table_name: nil, column_name: nil, job_arguments: [], **attributes|
+  define_method :matches? do |migration|
+    # Default arguments passed by BatchedMigrationWrapper (values don't matter here)
+    expect(migration).to be_background_migration_with_arguments([
+      _start_id = 1,
+      _stop_id = 2,
+      table_name,
+      column_name,
+      _sub_batch_size = 10,
+      _pause_ms = 100,
+      *job_arguments
+    ])
+
+    batched_migrations =
+      Gitlab::Database::BackgroundMigration::BatchedMigration
+        .for_configuration(migration, table_name, column_name, job_arguments)
+
+    expect(batched_migrations.count).to be(1)
+    expect(batched_migrations).to all(have_attributes(attributes)) if attributes.present?
+  end
+
+  define_method :does_not_match? do |migration|
+    batched_migrations =
+      Gitlab::Database::BackgroundMigration::BatchedMigration
+        .where(job_class_name: migration)
+
+    expect(batched_migrations.count).to be(0)
+  end
+end