diff --git a/db/docs/batched_background_migrations/update_workspaces_config_version3.yml b/db/docs/batched_background_migrations/update_workspaces_config_version3.yml
index 23fb5d60849e0bcbdb3a95fda468495b0f527816..155426f3c4ced3581a72b5d3c0db61c9173fa3b0 100644
--- a/db/docs/batched_background_migrations/update_workspaces_config_version3.yml
+++ b/db/docs/batched_background_migrations/update_workspaces_config_version3.yml
@@ -5,4 +5,4 @@ feature_category: remote_development
 introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/140972
 milestone: '16.8'
 queued_migration_version: 20240104085448
-finalized_by: # version of the migration that finalized this BBM
+finalized_by: 20240924214435
diff --git a/db/post_migrate/20240924214435_finalize_workspaces_config_version3_migration.rb b/db/post_migrate/20240924214435_finalize_workspaces_config_version3_migration.rb
new file mode 100644
index 0000000000000000000000000000000000000000..cfae892afe2fbd93bce962484dcaec8b72bedf81
--- /dev/null
+++ b/db/post_migrate/20240924214435_finalize_workspaces_config_version3_migration.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+class FinalizeWorkspacesConfigVersion3Migration < Gitlab::Database::Migration[2.2]
+  milestone '17.5'
+  MIGRATION = 'UpdateWorkspacesConfigVersion3'
+  disable_ddl_transaction!
+
+  restrict_gitlab_migration gitlab_schema: :gitlab_main
+
+  def up
+    ensure_batched_background_migration_is_finished(
+      job_class_name: MIGRATION,
+      table_name: :workspaces,
+      column_name: :config_version,
+      job_arguments: [],
+      finalize: true
+    )
+  end
+
+  def down
+    # no-op
+  end
+end
diff --git a/db/schema_migrations/20240924214435 b/db/schema_migrations/20240924214435
new file mode 100644
index 0000000000000000000000000000000000000000..0a0e7fe34ecb36f3f0f3e17507a7c1c7156a99f2
--- /dev/null
+++ b/db/schema_migrations/20240924214435
@@ -0,0 +1 @@
+a9a765bed96c7d69eac3cd0e41f373a68de7f88c09a143f0a4133506c10e93cd
\ No newline at end of file
diff --git a/ee/spec/lib/gitlab/background_migration/update_workspaces_config_version3_spec.rb b/ee/spec/lib/gitlab/background_migration/update_workspaces_config_version3_spec.rb
index 34b766205adf168be32a181e8a87b99d5508acf6..2c78e0bc5692b073b5ac58a4fbf0814590d81e87 100644
--- a/ee/spec/lib/gitlab/background_migration/update_workspaces_config_version3_spec.rb
+++ b/ee/spec/lib/gitlab/background_migration/update_workspaces_config_version3_spec.rb
@@ -2,7 +2,7 @@
 
 require 'spec_helper'
 
-RSpec.describe Gitlab::BackgroundMigration::UpdateWorkspacesConfigVersion3, feature_category: :workspaces do
+RSpec.describe Gitlab::BackgroundMigration::UpdateWorkspacesConfigVersion3, schema: 20240924214435, feature_category: :workspaces do
   describe "#perform" do
     let(:v2) { 2 }
     let(:v3) { 3 }
diff --git a/ee/spec/lib/gitlab/background_migration/update_workspaces_config_version_spec.rb b/ee/spec/lib/gitlab/background_migration/update_workspaces_config_version_spec.rb
deleted file mode 100644
index b65da081aae4e04c83b2e3142e7f1cf230a73414..0000000000000000000000000000000000000000
--- a/ee/spec/lib/gitlab/background_migration/update_workspaces_config_version_spec.rb
+++ /dev/null
@@ -1,101 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::BackgroundMigration::UpdateWorkspacesConfigVersion, feature_category: :workspaces do
-  describe "#perform" do
-    let(:v1) { RemoteDevelopment::WorkspaceOperations::ConfigVersion::VERSION_1 }
-    let(:v2) { RemoteDevelopment::WorkspaceOperations::ConfigVersion::VERSION_2 }
-    let(:personal_access_tokens_table) { table(:personal_access_tokens) }
-    let(:pat) do
-      personal_access_tokens_table.create!(name: 'workspace1', user_id: user.id, scopes: "---\n- api\n",
-        expires_at: 4.days.from_now)
-    end
-
-    let(:workspace_attrs) do
-      {
-        user_id: user.id,
-        project_id: project.id,
-        cluster_agent_id: cluster_agent.id,
-        personal_access_token_id: pat.id,
-        desired_state_updated_at: 2.seconds.ago,
-        max_hours_before_termination: 19,
-        namespace: 'ns',
-        desired_state: ::RemoteDevelopment::WorkspaceOperations::States::RUNNING,
-        editor: 'e',
-        devfile_ref: 'dfr',
-        devfile_path: 'dev/path',
-        url: 'https://www.example.org'
-      }
-    end
-
-    let(:namespace) { table(:namespaces).create!(name: 'namespace', path: 'namespace') }
-    let(:project) do
-      table(:projects).create!(name: 'project', path: 'project', project_namespace_id: namespace.id,
-        namespace_id: namespace.id)
-    end
-
-    let(:cluster_agent) { table(:cluster_agents).create!(name: 'cluster_agent', project_id: project.id) }
-    let(:user) { table(:users).create!(email: 'author@example.com', username: 'author', projects_limit: 10) }
-    let(:workspaces_table) { table(:workspaces) }
-    let!(:workspace_with_config_1_actual_state_terminated) do
-      workspaces_table.create!({
-        name: 'workspace1',
-        config_version: v1,
-        actual_state: ::RemoteDevelopment::WorkspaceOperations::States::TERMINATED,
-        force_include_all_resources: false
-      }.merge!(workspace_attrs))
-    end
-
-    let!(:workspace_with_config_1_actual_state_running) do
-      workspaces_table.create!({
-        name: 'workspace2',
-        config_version: v1,
-        actual_state: ::RemoteDevelopment::WorkspaceOperations::States::RUNNING
-      }.merge!(workspace_attrs))
-    end
-
-    let!(:workspace_with_config_2_actual_state_running) do
-      workspaces_table.create!({
-        name: 'workspace3',
-        config_version: v2,
-        actual_state: ::RemoteDevelopment::WorkspaceOperations::States::RUNNING,
-        force_include_all_resources: false
-      }.merge!(workspace_attrs))
-    end
-
-    let(:migration) do
-      described_class.new(
-        start_id: workspace_with_config_1_actual_state_terminated.id,
-        end_id: workspace_with_config_2_actual_state_running.id,
-        batch_table: :workspaces,
-        batch_column: :id,
-        sub_batch_size: 2,
-        pause_ms: 0,
-        connection: ApplicationRecord.connection
-      )
-    end
-
-    it "updates config_version and force_include_all_resources for existing non-terminated workspaces" do
-      migration.perform
-
-      workspace_with_config_1_actual_state_running.reload
-
-      expect(workspace_with_config_1_actual_state_running.config_version).to eq(v2)
-      expect(workspace_with_config_1_actual_state_running.force_include_all_resources).to eq(true)
-    end
-
-    it "does not update workspaces with different config_version or actual_state" do
-      migration.perform
-
-      workspace_with_config_1_actual_state_terminated.reload
-      workspace_with_config_2_actual_state_running.reload
-
-      expect(workspace_with_config_1_actual_state_terminated.config_version).to eq(v1)
-      expect(workspace_with_config_1_actual_state_terminated.force_include_all_resources).to eq(false)
-
-      expect(workspace_with_config_2_actual_state_running.config_version).to eq(v2)
-      expect(workspace_with_config_2_actual_state_running.force_include_all_resources).to eq(false)
-    end
-  end
-end