diff --git a/ee/config/metrics/counts_28d/20250301111827_created_service_accounts.yml b/ee/config/metrics/counts_28d/20250301111827_created_service_accounts.yml
new file mode 100644
index 0000000000000000000000000000000000000000..cf60d1c665e27888ec1b774eb347d97dcb00fa3c
--- /dev/null
+++ b/ee/config/metrics/counts_28d/20250301111827_created_service_accounts.yml
@@ -0,0 +1,16 @@
+---
+key_path: counts.created_service_accounts
+description: "Number of created service accounts every 28 days"
+product_group: authentication
+value_type: number
+status: active
+milestone: "17.10"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/183222
+time_frame: 28d
+data_source: database
+data_category: optional
+instrumentation_class: CountCreatedServiceAccountsMetric
+performance_indicator_type: []
+tiers:
+- premium
+- ultimate
diff --git a/ee/config/metrics/counts_28d/20250303180313_active_service_accounts.yml b/ee/config/metrics/counts_28d/20250303180313_active_service_accounts.yml
new file mode 100644
index 0000000000000000000000000000000000000000..9d941ba3dbecfbcdd47dcff108978fdd515b2312
--- /dev/null
+++ b/ee/config/metrics/counts_28d/20250303180313_active_service_accounts.yml
@@ -0,0 +1,16 @@
+---
+key_path: counts.active_service_accounts
+description: "Number of active service accounts every 28 days"
+product_group: authentication
+value_type: number
+status: active
+milestone: "17.10"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/183222
+time_frame: 28d
+data_source: database
+data_category: optional
+instrumentation_class: CountActiveServiceAccountsMetric
+performance_indicator_type: []
+tiers:
+- premium
+- ultimate
diff --git a/ee/lib/gitlab/usage/metrics/instrumentations/count_active_service_accounts_metric.rb b/ee/lib/gitlab/usage/metrics/instrumentations/count_active_service_accounts_metric.rb
new file mode 100644
index 0000000000000000000000000000000000000000..fee2bb8ae2ce2487d26854285ad6e59e6ab9febb
--- /dev/null
+++ b/ee/lib/gitlab/usage/metrics/instrumentations/count_active_service_accounts_metric.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+module Gitlab
+  module Usage
+    module Metrics
+      module Instrumentations
+        class CountActiveServiceAccountsMetric < DatabaseMetric
+          operation :distinct_count
+
+          timestamp_column :updated_at
+
+          relation do
+            User.service_account.where(state: 'active')
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/ee/lib/gitlab/usage/metrics/instrumentations/count_created_service_accounts_metric.rb b/ee/lib/gitlab/usage/metrics/instrumentations/count_created_service_accounts_metric.rb
new file mode 100644
index 0000000000000000000000000000000000000000..b83a54d94f1fd9ad363750d6e1deeb099001e9a1
--- /dev/null
+++ b/ee/lib/gitlab/usage/metrics/instrumentations/count_created_service_accounts_metric.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+module Gitlab
+  module Usage
+    module Metrics
+      module Instrumentations
+        class CountCreatedServiceAccountsMetric < DatabaseMetric
+          operation :distinct_count
+
+          timestamp_column :created_at
+
+          relation do
+            User.service_account
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/ee/spec/lib/gitlab/usage/metrics/instrumentations/count_active_service_accounts_metric_spec.rb b/ee/spec/lib/gitlab/usage/metrics/instrumentations/count_active_service_accounts_metric_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..678c3a723afc950087513057e98c782460368080
--- /dev/null
+++ b/ee/spec/lib/gitlab/usage/metrics/instrumentations/count_active_service_accounts_metric_spec.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Usage::Metrics::Instrumentations::CountActiveServiceAccountsMetric, feature_category: :service_ping do
+  context 'when the time_frame is 28 days' do
+    let_it_be(:service_account_created_within_28d) { create(:user, :service_account, updated_at: 3.days.ago) }
+
+    let_it_be(:expected_value) { 1 }
+
+    let(:old_time) { 30.days.ago.to_fs(:db) }
+    let(:recent_time) { 2.days.ago.to_fs(:db) }
+    let(:expected_query) do
+      <<~SQL.squish
+        SELECT COUNT(DISTINCT "users"."id")
+        FROM "users"
+        WHERE "users"."user_type" = 13
+        AND "users"."state" = 'active'
+        AND "users"."updated_at" BETWEEN '#{old_time}' AND '#{recent_time}'
+      SQL
+    end
+
+    it_behaves_like 'a correct instrumented metric value and query', { time_frame: '28d', data_source: 'database' }
+  end
+end
diff --git a/ee/spec/lib/gitlab/usage/metrics/instrumentations/count_created_service_accounts_metric_spec.rb b/ee/spec/lib/gitlab/usage/metrics/instrumentations/count_created_service_accounts_metric_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..5e11ce0d9d90365dcf11d0a92770287524d66625
--- /dev/null
+++ b/ee/spec/lib/gitlab/usage/metrics/instrumentations/count_created_service_accounts_metric_spec.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Usage::Metrics::Instrumentations::CountCreatedServiceAccountsMetric,
+  :aggregate_failures, feature_category: :service_ping do
+  context 'when the time_frame is 28 days' do
+    let_it_be(:service_account_created_within_28d) { create(:user, :service_account, created_at: 3.days.ago) }
+
+    let(:expected_value) { 1 }
+
+    let(:old_time) { 30.days.ago.to_fs(:db) }
+    let(:recent_time) { 2.days.ago.to_fs(:db) }
+    let(:expected_query) do
+      <<~SQL.squish
+        SELECT COUNT(DISTINCT "users"."id") FROM "users"
+        WHERE "users"."user_type" = 13 AND "users"."created_at"
+        BETWEEN '#{old_time}' AND '#{recent_time}'
+      SQL
+    end
+
+    it_behaves_like 'a correct instrumented metric value and query', { time_frame: '28d', data_source: 'database' }
+  end
+end