diff --git a/db/post_migrate/20230706080234_add_trigger_on_organizations.rb b/db/post_migrate/20230706080234_add_trigger_on_organizations.rb
new file mode 100644
index 0000000000000000000000000000000000000000..e21a5e0eb23b4e5e8c89c846c807446c11c59095
--- /dev/null
+++ b/db/post_migrate/20230706080234_add_trigger_on_organizations.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+class AddTriggerOnOrganizations < Gitlab::Database::Migration[2.1]
+  include Gitlab::Database::SchemaHelpers
+
+  TABLE_NAME = 'organizations'
+  FUNCTION_NAME = 'prevent_delete_of_default_organization'
+  TRIGGER_NAME = 'prevent_delete_of_default_organization_before_destroy'
+
+  def up
+    default_org_id = Organizations::Organization::DEFAULT_ORGANIZATION_ID
+
+    create_trigger_function(FUNCTION_NAME) do
+      <<~SQL
+        IF OLD.id = #{default_org_id} THEN
+          RAISE EXCEPTION 'Deletion of the default Organization is not allowed.';
+        END IF;
+        RETURN OLD;
+      SQL
+    end
+
+    create_trigger(TABLE_NAME, TRIGGER_NAME, FUNCTION_NAME, fires: 'BEFORE DELETE')
+  end
+
+  def down
+    drop_trigger(TABLE_NAME, TRIGGER_NAME)
+    drop_function(FUNCTION_NAME)
+  end
+end
diff --git a/db/schema_migrations/20230706080234 b/db/schema_migrations/20230706080234
new file mode 100644
index 0000000000000000000000000000000000000000..a188efbf3ca176a70085324a1666c76b640cf96c
--- /dev/null
+++ b/db/schema_migrations/20230706080234
@@ -0,0 +1 @@
+a76b57ff9a9e62c1e8d73c46a9bdf6512f0fe48d3b95b4c9a291d602d54d7a33
\ No newline at end of file
diff --git a/db/structure.sql b/db/structure.sql
index f50f65fbd6b8aa58d0e9605493b52ed85e027773..47bf58b83016b4c3ece05aa5cac0aad7e9bba9a5 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -191,6 +191,18 @@ CREATE FUNCTION postgres_pg_stat_activity_autovacuum() RETURNS TABLE(query text,
     AND backend_type = 'autovacuum worker'
 $$;
 
+CREATE FUNCTION prevent_delete_of_default_organization() RETURNS trigger
+    LANGUAGE plpgsql
+    AS $$
+BEGIN
+IF OLD.id = 1 THEN
+  RAISE EXCEPTION 'Deletion of the default Organization is not allowed.';
+END IF;
+RETURN OLD;
+
+END
+$$;
+
 CREATE FUNCTION set_has_external_issue_tracker() RETURNS trigger
     LANGUAGE plpgsql
     AS $$
@@ -35228,6 +35240,8 @@ CREATE TRIGGER organizations_loose_fk_trigger AFTER DELETE ON organizations REFE
 
 CREATE TRIGGER p_ci_builds_loose_fk_trigger AFTER DELETE ON p_ci_builds REFERENCING OLD TABLE AS old_table FOR EACH STATEMENT EXECUTE FUNCTION insert_into_loose_foreign_keys_deleted_records();
 
+CREATE TRIGGER prevent_delete_of_default_organization_before_destroy BEFORE DELETE ON organizations FOR EACH ROW EXECUTE FUNCTION prevent_delete_of_default_organization();
+
 CREATE TRIGGER projects_loose_fk_trigger AFTER DELETE ON projects REFERENCING OLD TABLE AS old_table FOR EACH STATEMENT EXECUTE FUNCTION insert_into_loose_foreign_keys_deleted_records();
 
 CREATE TRIGGER push_rules_loose_fk_trigger AFTER DELETE ON push_rules REFERENCING OLD TABLE AS old_table FOR EACH STATEMENT EXECUTE FUNCTION insert_into_loose_foreign_keys_deleted_records();
diff --git a/spec/models/organizations/organization_spec.rb b/spec/models/organizations/organization_spec.rb
index f462fbefcccec523d87abaa66ac57911d4130494..a9cac30e9a173a44f53dfe0e7bed5a37bc419828 100644
--- a/spec/models/organizations/organization_spec.rb
+++ b/spec/models/organizations/organization_spec.rb
@@ -148,4 +148,18 @@
       expect(organization.to_param).to eq('org_path')
     end
   end
+
+  context 'on deleting organizations via SQL' do
+    it 'does not allow to delete default organization' do
+      expect { default_organization.delete }.to raise_error(
+        ActiveRecord::StatementInvalid, /Deletion of the default Organization is not allowed/
+      )
+    end
+
+    it 'allows to delete any other organization' do
+      organization.delete
+
+      expect(described_class.where(id: organization)).not_to exist
+    end
+  end
 end