diff --git a/app/models/packages/nuget/symbol.rb b/app/models/packages/nuget/symbol.rb
index bbfaff3e8989d5b1aacce1b0a6ba124d6675a4f2..36213a85073cf9c08046a59802a37d204243687c 100644
--- a/app/models/packages/nuget/symbol.rb
+++ b/app/models/packages/nuget/symbol.rb
@@ -16,10 +16,10 @@ class Symbol < ApplicationRecord
 
       update_project_statistics project_statistics_name: :packages_size
 
-      validates :file, :file_path, :signature, :object_storage_key, :size, presence: true
-      validates :signature, uniqueness: { scope: %i[file_path package_id] }, if: -> { package }
+      validates :package, :file, :file_path, :signature, :object_storage_key, :size, presence: true
       validates :object_storage_key, uniqueness: true
-      validates :package, presence: true
+
+      validate :unique_signature_and_file_path_when_installable_package, on: :create
 
       sha256_attribute :file_sha256
 
@@ -32,6 +32,7 @@ class Symbol < ApplicationRecord
       scope :with_file_name, ->(file_name) { where(arel_table[:file].lower.eq(file_name.downcase)) }
       scope :with_signature, ->(signature) { where(arel_table[:signature].lower.eq(signature.downcase)) }
       scope :with_file_sha256, ->(checksums) { where(file_sha256: Array.wrap(checksums).map(&:downcase)) }
+      scope :with_file_path, ->(file_path) { where(arel_table[:file_path].lower.eq(file_path.downcase)) }
 
       def self.find_by_signature_and_file_and_checksum(signature, file_name, checksums)
         with_signature(signature)
@@ -51,6 +52,17 @@ def set_object_storage_key
           root_hash: project_id
         ).to_s
       end
+
+      def unique_signature_and_file_path_when_installable_package
+        return if errors.any?
+
+        return unless ::Packages::Package
+                        .id_in(self.class.with_signature(signature).with_file_path(file_path).select(:package_id))
+                        .installable
+                        .exists?
+
+        errors.add(:signature, 'has already been taken')
+      end
     end
   end
 end
diff --git a/app/services/packages/nuget/symbols/create_symbol_files_service.rb b/app/services/packages/nuget/symbols/create_symbol_files_service.rb
index be931413ae6c99f11087de9f0d6d7670a1f96ff0..9de32dab18f39cbab394e0eff8230e1ed588fd86 100644
--- a/app/services/packages/nuget/symbols/create_symbol_files_service.rb
+++ b/app/services/packages/nuget/symbols/create_symbol_files_service.rb
@@ -46,8 +46,7 @@ def create_symbol(path, file)
           signature, checksum = extract_signature_and_checksum(file)
           return if signature.blank? || checksum.blank?
 
-          ::Packages::Nuget::Symbol.create!(
-            package: package,
+          package.nuget_symbols.create(
             file: { tempfile: file, filename: path.downcase, content_type: CONTENT_TYPE },
             file_path: path,
             signature: signature,
diff --git a/db/migrate/20241217093056_add_index_packages_nuget_symbols_on_lower_signature_and_filepath.rb b/db/migrate/20241217093056_add_index_packages_nuget_symbols_on_lower_signature_and_filepath.rb
new file mode 100644
index 0000000000000000000000000000000000000000..76102189a2061c6643cd571db79ca124c3b49e5e
--- /dev/null
+++ b/db/migrate/20241217093056_add_index_packages_nuget_symbols_on_lower_signature_and_filepath.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class AddIndexPackagesNugetSymbolsOnLowerSignatureAndFilepath < Gitlab::Database::Migration[2.2]
+  disable_ddl_transaction!
+  milestone '17.8'
+
+  TABLE_NAME = :packages_nuget_symbols
+  INDEX_NAME = :idx_pkgs_nuget_symbols_on_lowercase_signature_and_file_path
+
+  def up
+    add_concurrent_index TABLE_NAME, 'LOWER(signature), LOWER(file_path)', name: INDEX_NAME
+  end
+
+  def down
+    remove_concurrent_index_by_name TABLE_NAME, INDEX_NAME
+  end
+end
diff --git a/db/post_migrate/20241205142115_remove_index_packages_nuget_symbols_on_signature_and_filepath_with_pkg.rb b/db/post_migrate/20241205142115_remove_index_packages_nuget_symbols_on_signature_and_filepath_with_pkg.rb
new file mode 100644
index 0000000000000000000000000000000000000000..0b645d8be2b5a861e12e5c8324145437313b48aa
--- /dev/null
+++ b/db/post_migrate/20241205142115_remove_index_packages_nuget_symbols_on_signature_and_filepath_with_pkg.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+class RemoveIndexPackagesNugetSymbolsOnSignatureAndFilepathWithPkg < Gitlab::Database::Migration[2.2]
+  disable_ddl_transaction!
+  milestone '17.8'
+
+  TABLE_NAME = :packages_nuget_symbols
+  INDEX_NAME = :idx_pkgs_nuget_symbols_on_signature_and_file_path_with_pkg_id
+
+  def up
+    remove_concurrent_index_by_name TABLE_NAME, INDEX_NAME
+  end
+
+  def down
+    add_concurrent_index(
+      TABLE_NAME,
+      %i[signature file_path],
+      unique: true,
+      name: INDEX_NAME,
+      where: 'package_id IS NOT NULL'
+    )
+  end
+end
diff --git a/db/schema_migrations/20241205142115 b/db/schema_migrations/20241205142115
new file mode 100644
index 0000000000000000000000000000000000000000..7e0b83b76a036d212dd0c9cd329c9cf1a7a5003b
--- /dev/null
+++ b/db/schema_migrations/20241205142115
@@ -0,0 +1 @@
+02dca3a01bfdca1ca3ba2fb75689d39f580923739c6edc19b047b97c250e1f14
\ No newline at end of file
diff --git a/db/schema_migrations/20241217093056 b/db/schema_migrations/20241217093056
new file mode 100644
index 0000000000000000000000000000000000000000..c89b7bf9389096d3a7327f46ff874c8329dabdaf
--- /dev/null
+++ b/db/schema_migrations/20241217093056
@@ -0,0 +1 @@
+e840562920a4271e12412d7600f7702eaa99e41f97a0a9b23469388966085a9c
\ No newline at end of file
diff --git a/db/structure.sql b/db/structure.sql
index 2b7520aaaf419107545e938668ecf78e50249c27..91bbe9995ea3eb755760587f93b52f596af7e278 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -29074,7 +29074,7 @@ CREATE INDEX idx_pkgs_npm_metadata_caches_on_id_and_project_id_and_status ON pac
 
 CREATE INDEX idx_pkgs_nuget_symbols_on_lowercase_signature_and_file_name ON packages_nuget_symbols USING btree (lower(signature), lower(file));
 
-CREATE UNIQUE INDEX idx_pkgs_nuget_symbols_on_signature_and_file_path_with_pkg_id ON packages_nuget_symbols USING btree (signature, file_path) WHERE (package_id IS NOT NULL);
+CREATE INDEX idx_pkgs_nuget_symbols_on_lowercase_signature_and_file_path ON packages_nuget_symbols USING btree (lower(signature), lower(file_path));
 
 CREATE INDEX idx_pkgs_on_project_id_name_version_on_installable_terraform ON packages_packages USING btree (project_id, name, version, id) WHERE ((package_type = 12) AND (status = ANY (ARRAY[0, 1])));
 
diff --git a/spec/models/packages/nuget/symbol_spec.rb b/spec/models/packages/nuget/symbol_spec.rb
index b4a5eb019964e0d6df91975805394f7b78001c97..018dc93e671dfe157d10dd7f43a1a89830a2a738 100644
--- a/spec/models/packages/nuget/symbol_spec.rb
+++ b/spec/models/packages/nuget/symbol_spec.rb
@@ -26,18 +26,55 @@
     it { is_expected.to validate_presence_of(:object_storage_key) }
     it { is_expected.to validate_presence_of(:size) }
     it { is_expected.to validate_uniqueness_of(:object_storage_key).case_insensitive }
-    it { is_expected.to validate_uniqueness_of(:signature).scoped_to(:file_path, :package_id) }
 
-    context 'when package is nil' do
+    context 'for signature & file_path uniqueness' do
       let(:new_symbol) { build(:nuget_symbol, signature: symbol.signature) }
 
-      before do
-        new_symbol.package = nil
-        new_symbol.validate
+      context 'when package is nil' do
+        before do
+          symbol.package = nil
+          new_symbol.validate
+        end
+
+        it 'does not validate uniqueness of signature' do
+          expect(new_symbol.errors.messages_for(:signature)).not_to include 'has already been taken'
+        end
       end
 
-      it 'does not validate uniqueness of signature' do
-        expect(new_symbol.errors.messages_for(:signature)).not_to include 'has already been taken'
+      context 'when package is installable' do
+        before do
+          new_symbol.object_storage_key = '123/foobar/456'
+          new_symbol.validate
+        end
+
+        it 'validates uniqueness of signature' do
+          expect(new_symbol.errors.messages_for(:signature)).to include 'has already been taken'
+        end
+      end
+
+      context 'when package is not installable' do
+        before do
+          new_symbol.package = symbol.package if package_exists
+          symbol.package.update_column(:status, :pending_destruction)
+          new_symbol.object_storage_key = '123/foobar/456'
+          new_symbol.validate
+        end
+
+        context 'and package already exists' do
+          let(:package_exists) { true }
+
+          it 'does not validate uniqueness of signature' do
+            expect(new_symbol.errors.messages_for(:signature)).not_to include 'has already been taken'
+          end
+        end
+
+        context 'and package does not exist' do
+          let(:package_exists) { false }
+
+          it 'does not validate uniqueness of signature' do
+            expect(new_symbol.errors.messages_for(:signature)).not_to include 'has already been taken'
+          end
+        end
       end
     end
   end
@@ -120,6 +157,21 @@
       end
     end
 
+    describe '.with_file_path' do
+      let_it_be(:file_path) { 'symbol_package/file.pdb' }
+      let_it_be(:symbol) { create(:nuget_symbol, file_path: file_path) }
+
+      subject { described_class.with_file_path(file_path) }
+
+      it { is_expected.to contain_exactly(symbol) }
+
+      context 'when file_path is in uppercase' do
+        subject { described_class.with_file_path(file_path.upcase) }
+
+        it { is_expected.to contain_exactly(symbol) }
+      end
+    end
+
     describe '.find_by_signature_and_file_and_checksum' do
       subject { described_class.find_by_signature_and_file_and_checksum(signature, file_name, checksum) }
 
diff --git a/spec/services/packages/nuget/symbols/create_symbol_files_service_spec.rb b/spec/services/packages/nuget/symbols/create_symbol_files_service_spec.rb
index 9707386ec21fcc95b573b243c8b60b1af74bd10d..01a86d7eb3d995b4d3dfd7d6cff9134532eee387 100644
--- a/spec/services/packages/nuget/symbols/create_symbol_files_service_spec.rb
+++ b/spec/services/packages/nuget/symbols/create_symbol_files_service_spec.rb
@@ -93,8 +93,6 @@
       it 'does not create a symbol record' do
         expect { subject }.not_to change { package.nuget_symbols.count }
       end
-
-      it_behaves_like 'logging an error', ActiveRecord::RecordInvalid
     end
 
     context 'when a symbol file has the wrong entry size' do