diff --git a/app/models/integrations/instance_integration.rb b/app/models/integrations/instance_integration.rb
new file mode 100644
index 0000000000000000000000000000000000000000..9fc52fb570808eda0365880cde76c3dcd8dc82d0
--- /dev/null
+++ b/app/models/integrations/instance_integration.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+module Integrations
+  class InstanceIntegration < Integration
+    self.table_name = 'instance_integrations'
+  end
+end
diff --git a/db/docs/instance_integrations.yml b/db/docs/instance_integrations.yml
new file mode 100644
index 0000000000000000000000000000000000000000..b799f7a5a5b21a79c78522993f8a29cfab06fa0f
--- /dev/null
+++ b/db/docs/instance_integrations.yml
@@ -0,0 +1,10 @@
+---
+table_name: instance_integrations
+classes:
+- Integrations::InstanceIntegration
+feature_categories:
+- integrations
+description: Support 3rd party instance-wide integrations
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/164503
+milestone: '17.4'
+gitlab_schema: gitlab_main_clusterwide
diff --git a/db/migrate/20240829163210_create_instance_integrations_table.rb b/db/migrate/20240829163210_create_instance_integrations_table.rb
new file mode 100644
index 0000000000000000000000000000000000000000..85128e8dc865c7c761639e95d2599bad42f971fd
--- /dev/null
+++ b/db/migrate/20240829163210_create_instance_integrations_table.rb
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+
+class CreateInstanceIntegrationsTable < Gitlab::Database::Migration[2.2]
+  milestone '17.4'
+
+  # rubocop:disable Migration/EnsureFactoryForTable -- False Positive
+  def up
+    create_table :instance_integrations, id: :bigserial do |t|
+      t.timestamps_with_timezone null: false
+      t.integer :comment_detail
+      t.boolean :active, default: false, null: false
+      t.boolean :push_events, default: true
+      t.boolean :issues_events, default: true
+      t.boolean :merge_requests_events, default: true
+      t.boolean :tag_push_events, default: true
+      t.boolean :note_events, default: true, null: false
+      t.boolean :wiki_page_events, default: true
+      t.boolean :pipeline_events, default: false, null: false
+      t.boolean :confidential_issues_events, default: true, null: false
+      t.boolean :commit_events, default: true, null: false
+      t.boolean :job_events, default: false, null: false
+      t.boolean :confidential_note_events, default: true
+      t.boolean :deployment_events, default: false, null: false
+      t.boolean :comment_on_event_enabled, default: true, null: false
+      t.boolean :alert_events
+      t.boolean :vulnerability_events, default: false, null: false
+      t.boolean :archive_trace_events, default: false, null: false
+      t.boolean :incident_events, default: false, null: false
+      t.boolean :group_mention_events, default: false, null: false
+      t.boolean :group_confidential_mention_events, default: false, null: false
+      t.text :category, default: 'common', limit: 255
+      t.text :type, limit: 255
+      t.binary :encrypted_properties
+      t.binary :encrypted_properties_iv
+    end
+  end
+  # rubocop:enable Migration/EnsureFactoryForTable -- False Positive
+
+  def down
+    drop_table :instance_integrations, if_exists: true
+  end
+end
diff --git a/db/schema_migrations/20240829163210 b/db/schema_migrations/20240829163210
new file mode 100644
index 0000000000000000000000000000000000000000..ebc3b67fc32a4f2b7faf97422ed3018e05d9bb6f
--- /dev/null
+++ b/db/schema_migrations/20240829163210
@@ -0,0 +1 @@
+7f15b5117aa826e8e0dbbd334393a29c4da7bc6443308f1ceffbaa015ab999cd
\ No newline at end of file
diff --git a/db/structure.sql b/db/structure.sql
index 409fc6aef8f96b6399a49d99c9c43c7960c4b634..bc19fdb661f853fec2d379f26e2e0fbead8bd16d 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -12059,6 +12059,48 @@ CREATE SEQUENCE instance_audit_events_streaming_headers_id_seq
 
 ALTER SEQUENCE instance_audit_events_streaming_headers_id_seq OWNED BY instance_audit_events_streaming_headers.id;
 
+CREATE TABLE instance_integrations (
+    id bigint NOT NULL,
+    created_at timestamp with time zone NOT NULL,
+    updated_at timestamp with time zone NOT NULL,
+    comment_detail integer,
+    active boolean DEFAULT false NOT NULL,
+    push_events boolean DEFAULT true,
+    issues_events boolean DEFAULT true,
+    merge_requests_events boolean DEFAULT true,
+    tag_push_events boolean DEFAULT true,
+    note_events boolean DEFAULT true NOT NULL,
+    wiki_page_events boolean DEFAULT true,
+    pipeline_events boolean DEFAULT false NOT NULL,
+    confidential_issues_events boolean DEFAULT true NOT NULL,
+    commit_events boolean DEFAULT true NOT NULL,
+    job_events boolean DEFAULT false NOT NULL,
+    confidential_note_events boolean DEFAULT true,
+    deployment_events boolean DEFAULT false NOT NULL,
+    comment_on_event_enabled boolean DEFAULT true NOT NULL,
+    alert_events boolean,
+    vulnerability_events boolean DEFAULT false NOT NULL,
+    archive_trace_events boolean DEFAULT false NOT NULL,
+    incident_events boolean DEFAULT false NOT NULL,
+    group_mention_events boolean DEFAULT false NOT NULL,
+    group_confidential_mention_events boolean DEFAULT false NOT NULL,
+    category text DEFAULT 'common'::text,
+    type text,
+    encrypted_properties bytea,
+    encrypted_properties_iv bytea,
+    CONSTRAINT check_611836812c CHECK ((char_length(category) <= 255)),
+    CONSTRAINT check_69b7b09aa8 CHECK ((char_length(type) <= 255))
+);
+
+CREATE SEQUENCE instance_integrations_id_seq
+    START WITH 1
+    INCREMENT BY 1
+    NO MINVALUE
+    NO MAXVALUE
+    CACHE 1;
+
+ALTER SEQUENCE instance_integrations_id_seq OWNED BY instance_integrations.id;
+
 CREATE TABLE integrations (
     id bigint NOT NULL,
     project_id bigint,
@@ -21710,6 +21752,8 @@ ALTER TABLE ONLY insights ALTER COLUMN id SET DEFAULT nextval('insights_id_seq':
 
 ALTER TABLE ONLY instance_audit_events_streaming_headers ALTER COLUMN id SET DEFAULT nextval('instance_audit_events_streaming_headers_id_seq'::regclass);
 
+ALTER TABLE ONLY instance_integrations ALTER COLUMN id SET DEFAULT nextval('instance_integrations_id_seq'::regclass);
+
 ALTER TABLE ONLY integrations ALTER COLUMN id SET DEFAULT nextval('integrations_id_seq'::regclass);
 
 ALTER TABLE ONLY internal_ids ALTER COLUMN id SET DEFAULT nextval('internal_ids_id_seq'::regclass);
@@ -23974,6 +24018,9 @@ ALTER TABLE ONLY instance_audit_events
 ALTER TABLE ONLY instance_audit_events_streaming_headers
     ADD CONSTRAINT instance_audit_events_streaming_headers_pkey PRIMARY KEY (id);
 
+ALTER TABLE ONLY instance_integrations
+    ADD CONSTRAINT instance_integrations_pkey PRIMARY KEY (id);
+
 ALTER TABLE ONLY integrations
     ADD CONSTRAINT integrations_pkey PRIMARY KEY (id);
 
diff --git a/spec/factories/integrations/instance_integrations.rb b/spec/factories/integrations/instance_integrations.rb
new file mode 100644
index 0000000000000000000000000000000000000000..d70b7ecf889682d955dc7bf9800b7e0860528958
--- /dev/null
+++ b/spec/factories/integrations/instance_integrations.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+  factory :instance_integration, class: 'Integrations::InstanceIntegration' do
+    type { 'Integrations::InstanceIntegration' }
+  end
+end