diff --git a/config/audit_events/types/self_hosted_model_destroyed.yml b/config/audit_events/types/self_hosted_model_destroyed.yml
new file mode 100644
index 0000000000000000000000000000000000000000..970227e234711d5f227551485429ac4b6b468865
--- /dev/null
+++ b/config/audit_events/types/self_hosted_model_destroyed.yml
@@ -0,0 +1,9 @@
+name: self_hosted_model_destroyed
+description: A new self-hosted model configuration was destroyed
+introduced_by_issue: https://gitlab.com/gitlab-org/gitlab/-/issues/477999
+introduced_by_mr: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/165321
+feature_category: self-hosted_models
+milestone: '17.4'
+saved_to_database: true
+scope: [Instance, User]
+streamed: true
diff --git a/doc/user/compliance/audit_event_types.md b/doc/user/compliance/audit_event_types.md
index 2975ebb088a6415c7bd34c8eef44560ce3f83b21..7bb4011e38c1eb39f3ad37ebafddca3394f4735a 100644
--- a/doc/user/compliance/audit_event_types.md
+++ b/doc/user/compliance/audit_event_types.md
@@ -453,6 +453,7 @@ Audit event types belong to the following product categories.
 
 | Name | Description | Saved to database | Streamed | Introduced in | Scope |
 |:------------|:------------|:------------------|:---------|:--------------|:--------------|
+| [`self_hosted_model_destroyed`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/165321) | A new self-hosted model configuration was destroyed | **{check-circle}** Yes | **{check-circle}** Yes | GitLab [17.4](https://gitlab.com/gitlab-org/gitlab/-/issues/477999) | Instance, User |
 | [`self_hosted_model_feature_changed`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/165489) | A self-hosted model feature had its configuration changed | **{check-circle}** Yes | **{check-circle}** Yes | GitLab [17.4](https://gitlab.com/gitlab-org/gitlab/-/issues/463215) | Project |
 | [`self_hosted_model_terms_accepted`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/165480) | Terms for usage of self-hosted models were accepted | **{check-circle}** Yes | **{check-circle}** Yes | GitLab [17.4](https://gitlab.com/gitlab-org/gitlab/-/issues/477999) | Instance, User |
 
diff --git a/ee/app/controllers/admin/ai/self_hosted_models_controller.rb b/ee/app/controllers/admin/ai/self_hosted_models_controller.rb
index 7d8cead2550689473b249197af1915189a57bd9b..8e05afe3a9a19709c0804b378698da53400d4252 100644
--- a/ee/app/controllers/admin/ai/self_hosted_models_controller.rb
+++ b/ee/app/controllers/admin/ai/self_hosted_models_controller.rb
@@ -46,7 +46,9 @@ def update
       def destroy
         @self_hosted_model = ::Ai::SelfHostedModel.find(params[:id])
 
-        if @self_hosted_model.destroy
+        result = ::Ai::SelfHostedModels::DestroyService.new(@self_hosted_model, current_user).execute
+
+        if result.success?
           redirect_to admin_ai_self_hosted_models_url, notice: _("Self-Hosted Model was deleted")
         else
           render :index
diff --git a/ee/app/graphql/mutations/ai/self_hosted_models/delete.rb b/ee/app/graphql/mutations/ai/self_hosted_models/delete.rb
index c178f33e9a58ff090357de6406b0871274e30fcf..efb2e407d6cc95f783eeb5b13b6a7b605e8d0d51 100644
--- a/ee/app/graphql/mutations/ai/self_hosted_models/delete.rb
+++ b/ee/app/graphql/mutations/ai/self_hosted_models/delete.rb
@@ -15,28 +15,20 @@ class Delete < Base
         def resolve(**args)
           check_feature_access!
 
-          result = delete_self_hosted_model(args)
-
-          if result[:errors].present?
-            {
-              self_hosted_model: nil,
-              errors: Array(result[:errors])
-            }
-          else
-            { self_hosted_model: result, errors: [] }
-          end
-        end
-
-        private
-
-        def delete_self_hosted_model(args)
           model = find_object(id: args[:id])
 
           return { errors: ["Self-hosted model not found"] } unless model
 
-          model.destroy
+          result = ::Ai::SelfHostedModels::DestroyService.new(model, current_user).execute
+
+          {
+            self_hosted_model: result.success? ? result.payload : nil,
+            errors: result.error? ? Array.wrap(result.errors) : []
+          }
         end
 
+        private
+
         def find_object(id:)
           GitlabSchema.object_from_id(id, expected_type: ::Ai::SelfHostedModel).sync
         end
diff --git a/ee/app/services/ai/self_hosted_models/destroy_service.rb b/ee/app/services/ai/self_hosted_models/destroy_service.rb
new file mode 100644
index 0000000000000000000000000000000000000000..b98c9ebde737c2ec07802219322c4e18ed664739
--- /dev/null
+++ b/ee/app/services/ai/self_hosted_models/destroy_service.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+module Ai
+  module SelfHostedModels
+    class DestroyService
+      def initialize(self_hosted_model, user)
+        @self_hosted_model = self_hosted_model
+        @user = user
+      end
+
+      def execute
+        if self_hosted_model.destroy
+          audit_destroy_event
+
+          ServiceResponse.success(payload: self_hosted_model)
+        else
+          ServiceResponse.error(message: self_hosted_model.errors.full_messages.join(", "))
+        end
+      end
+
+      private
+
+      attr_accessor :self_hosted_model, :user
+
+      def audit_destroy_event
+        model = self_hosted_model
+        audit_context = {
+          name: 'self_hosted_model_destroyed',
+          author: user,
+          scope: user,
+          target: model,
+          message: "Self-hosted model #{model.name}/#{model.model}/#{model.endpoint} destroyed"
+        }
+
+        ::Gitlab::Audit::Auditor.audit(audit_context)
+      end
+    end
+  end
+end
diff --git a/ee/spec/services/ai/self_hosted_models/destroy_service_spec.rb b/ee/spec/services/ai/self_hosted_models/destroy_service_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..e37eb86d7d4c1f1b5979b2bf6a2170f7da45a0d8
--- /dev/null
+++ b/ee/spec/services/ai/self_hosted_models/destroy_service_spec.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ::Ai::SelfHostedModels::DestroyService, feature_category: :"self-hosted_models" do
+  let_it_be(:user) { create(:user) }
+
+  let(:self_hosted_model) { create(:ai_self_hosted_model) }
+
+  let(:service) { described_class.new(self_hosted_model, user) }
+
+  let(:audit_event) do
+    model = self_hosted_model
+    {
+      name: 'self_hosted_model_destroyed',
+      author: user,
+      scope: user,
+      target: model,
+      message: "Self-hosted model #{model.name}/#{model.model}/#{model.endpoint} destroyed"
+    }
+  end
+
+  describe '#execute', :aggregate_failures do
+    subject(:result) { service.execute }
+
+    context 'when the model is successfully destroyed' do
+      it 'returns a success response' do
+        expect(Gitlab::Audit::Auditor).to receive(:audit).with(audit_event)
+
+        expect { result }.to change { ::Ai::SelfHostedModel.count }.by(-1)
+
+        expect(result).to be_success
+        expect(result.payload).to eq(self_hosted_model)
+      end
+    end
+
+    context 'when the model fails to be destroyed' do
+      before do
+        allow(self_hosted_model).to receive(:destroy).and_return(false)
+        allow(self_hosted_model).to receive_message_chain(:errors, :full_messages).and_return(['Error message'])
+      end
+
+      it 'returns an error response' do
+        expect(Gitlab::Audit::Auditor).not_to receive(:audit)
+        expect { result }.not_to change { ::Ai::SelfHostedModel.count }
+
+        expect(result).to be_error
+        expect(result.message).to eq('Error message')
+      end
+    end
+  end
+end