diff --git a/db/post_migrate/20230717144729_drop_ci_job_artifacts_partition_id_default_v2.rb b/db/post_migrate/20230717144729_drop_ci_job_artifacts_partition_id_default_v2.rb
new file mode 100644
index 0000000000000000000000000000000000000000..a3b2cd324fb8be6eaeb476ff72f91da5863b5b56
--- /dev/null
+++ b/db/post_migrate/20230717144729_drop_ci_job_artifacts_partition_id_default_v2.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+class DropCiJobArtifactsPartitionIdDefaultV2 < Gitlab::Database::Migration[2.1]
+  enable_lock_retries!
+
+  TABLE_NAME = :ci_job_artifacts
+  COLUMN_NAME = :partition_id
+
+  def up
+    remove_column_default(TABLE_NAME, COLUMN_NAME)
+  end
+
+  def down
+    change_column_default(TABLE_NAME, COLUMN_NAME, from: nil, to: 100)
+  end
+end
diff --git a/db/post_migrate/20230717144744_drop_ci_stages_partition_id_default_v2.rb b/db/post_migrate/20230717144744_drop_ci_stages_partition_id_default_v2.rb
new file mode 100644
index 0000000000000000000000000000000000000000..d32b871828161a1ea79394720a99bd8259b045fc
--- /dev/null
+++ b/db/post_migrate/20230717144744_drop_ci_stages_partition_id_default_v2.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+class DropCiStagesPartitionIdDefaultV2 < Gitlab::Database::Migration[2.1]
+  enable_lock_retries!
+
+  TABLE_NAME = :ci_stages
+  COLUMN_NAME = :partition_id
+
+  def up
+    remove_column_default(TABLE_NAME, COLUMN_NAME)
+  end
+
+  def down
+    change_column_default(TABLE_NAME, COLUMN_NAME, from: nil, to: 100)
+  end
+end
diff --git a/db/post_migrate/20230717144802_drop_ci_build_trace_metadata_partition_id_default_v2.rb b/db/post_migrate/20230717144802_drop_ci_build_trace_metadata_partition_id_default_v2.rb
new file mode 100644
index 0000000000000000000000000000000000000000..e189801c79b27af1f8ef40112a744f1f00ad5d0d
--- /dev/null
+++ b/db/post_migrate/20230717144802_drop_ci_build_trace_metadata_partition_id_default_v2.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+class DropCiBuildTraceMetadataPartitionIdDefaultV2 < Gitlab::Database::Migration[2.1]
+  enable_lock_retries!
+
+  TABLE_NAME = :ci_build_trace_metadata
+  COLUMN_NAME = :partition_id
+
+  def up
+    remove_column_default(TABLE_NAME, COLUMN_NAME)
+  end
+
+  def down
+    change_column_default(TABLE_NAME, COLUMN_NAME, from: nil, to: 100)
+  end
+end
diff --git a/db/post_migrate/20230717144817_drop_ci_pipeline_variable_partition_id_default_v2.rb b/db/post_migrate/20230717144817_drop_ci_pipeline_variable_partition_id_default_v2.rb
new file mode 100644
index 0000000000000000000000000000000000000000..c75c0226b15d0b173ffeb46c30fb0e0dbd77b261
--- /dev/null
+++ b/db/post_migrate/20230717144817_drop_ci_pipeline_variable_partition_id_default_v2.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+class DropCiPipelineVariablePartitionIdDefaultV2 < Gitlab::Database::Migration[2.1]
+  enable_lock_retries!
+
+  TABLE_NAME = :ci_pipeline_variables
+  COLUMN_NAME = :partition_id
+
+  def up
+    remove_column_default(TABLE_NAME, COLUMN_NAME)
+  end
+
+  def down
+    change_column_default(TABLE_NAME, COLUMN_NAME, from: nil, to: 100)
+  end
+end
diff --git a/db/schema_migrations/20230717144729 b/db/schema_migrations/20230717144729
new file mode 100644
index 0000000000000000000000000000000000000000..786c5fe295beb1cd2b5a2b128629439ac0197248
--- /dev/null
+++ b/db/schema_migrations/20230717144729
@@ -0,0 +1 @@
+a9264babc5e84597c2f8fb2fb2a3df4dceb0f6fe83877d18df03e679c77afa1b
\ No newline at end of file
diff --git a/db/schema_migrations/20230717144744 b/db/schema_migrations/20230717144744
new file mode 100644
index 0000000000000000000000000000000000000000..c643d8d90dcf4dc67f62745ce6497f7556fadb71
--- /dev/null
+++ b/db/schema_migrations/20230717144744
@@ -0,0 +1 @@
+2ed2825eb5a1adaf1456096c84c0bc4016374e5525defa31b8c1393a8d864007
\ No newline at end of file
diff --git a/db/schema_migrations/20230717144802 b/db/schema_migrations/20230717144802
new file mode 100644
index 0000000000000000000000000000000000000000..12494fd21043706fcdb482d2d49b03b8d1326e4e
--- /dev/null
+++ b/db/schema_migrations/20230717144802
@@ -0,0 +1 @@
+eed3845b0321cdb69c7dfe8e54dda940362f1bc99405727eb252744cda254522
\ No newline at end of file
diff --git a/db/schema_migrations/20230717144817 b/db/schema_migrations/20230717144817
new file mode 100644
index 0000000000000000000000000000000000000000..d16daa2fad6d4b0f1ce28a12b1fe412b635fb8e5
--- /dev/null
+++ b/db/schema_migrations/20230717144817
@@ -0,0 +1 @@
+18f72f73afe0fb027df28f6bc915f8afc1460258b08038055ee9c48a6d2bfbeb
\ No newline at end of file
diff --git a/lib/gitlab/database/migration_helpers.rb b/lib/gitlab/database/migration_helpers.rb
index 256c524e989d5c6457debea662a2c6740e7615dc..60cec12b4b5aa720384918d93aab07b523b88d5f 100644
--- a/lib/gitlab/database/migration_helpers.rb
+++ b/lib/gitlab/database/migration_helpers.rb
@@ -1191,6 +1191,19 @@ def table_partitioned?(table_name)
           .present?
       end
 
+      # While it is safe to call `change_column_default` on a column without
+      # default it would still require access exclusive lock on the table
+      # and for tables with high autovacuum(wraparound prevention) it will
+      # fail if their executions overlap.
+      #
+      def remove_column_default(table_name, column_name)
+        column = connection.columns(table_name).find { |col| col.name == column_name.to_s }
+
+        if column.default || column.default_function
+          change_column_default(table_name, column_name, to: nil)
+        end
+      end
+
       private
 
       def multiple_columns(columns, separator: ', ')
diff --git a/spec/lib/gitlab/database/migration_helpers_spec.rb b/spec/lib/gitlab/database/migration_helpers_spec.rb
index b1e8301d69f610501775b9434ff5e6a8bec90de1..f3c181db3aacbb83ffe527ad0f79113c4969e96c 100644
--- a/spec/lib/gitlab/database/migration_helpers_spec.rb
+++ b/spec/lib/gitlab/database/migration_helpers_spec.rb
@@ -2867,4 +2867,43 @@ def setup
       it { is_expected.to be_falsey }
     end
   end
+
+  describe '#remove_column_default' do
+    let(:test_table) { :_test_defaults_table }
+    let(:drop_default_statement) do
+      /ALTER TABLE "#{test_table}" ALTER COLUMN "#{column_name}" SET DEFAULT NULL/
+    end
+
+    subject(:recorder) do
+      ActiveRecord::QueryRecorder.new do
+        model.remove_column_default(test_table, column_name)
+      end
+    end
+
+    before do
+      model.create_table(test_table) do |t|
+        t.integer :int_with_default, default: 100
+        t.integer :int_with_default_function, default: -> { 'ceil(random () * 100)::int' }
+        t.integer :int_without_default
+      end
+    end
+
+    context 'with default values' do
+      let(:column_name) { :int_with_default }
+
+      it { expect(recorder.log).to include(drop_default_statement) }
+    end
+
+    context 'with default functions' do
+      let(:column_name) { :int_with_default_function }
+
+      it { expect(recorder.log).to include(drop_default_statement) }
+    end
+
+    context 'without any defaults' do
+      let(:column_name) { :int_without_default }
+
+      it { expect(recorder.log).to be_empty }
+    end
+  end
 end