diff --git a/changelogs/unreleased/221184-rolling-28-day-deployments-metrics.yml b/changelogs/unreleased/221184-rolling-28-day-deployments-metrics.yml
new file mode 100644
index 0000000000000000000000000000000000000000..772b40854a3aa925397fd4ec72c6d47653b65b3f
--- /dev/null
+++ b/changelogs/unreleased/221184-rolling-28-day-deployments-metrics.yml
@@ -0,0 +1,5 @@
+---
+title: Rolling 28 day time period counter for deployments
+merge_request: 35493
+author:
+type: added
diff --git a/doc/development/telemetry/usage_ping.md b/doc/development/telemetry/usage_ping.md
index a31a6ddb3dbf0a12bd9edb9f82851768b3072049..c0bc986379c6d721fdcd0390d409e353dbc843f3 100644
--- a/doc/development/telemetry/usage_ping.md
+++ b/doc/development/telemetry/usage_ping.md
@@ -422,9 +422,12 @@ appear to be associated to any of the services running, since they all appear to
 | `auto_devops_disabled`                                    | `counts`                             | `configure`   |                  |         | Projects with Auto DevOps template disabled                                |
 | `deploy_keys`                                             | `counts`                             |               |                  |         |                                                                            |
 | `deployments`                                             | `counts`                             | `release`     |                  |         | Total deployments                                                          |
+| `deployments`                                             | `counts_monthly`                     | `release`     |                  |         | Total deployments last 28 days                                             |
 | `dast_jobs`                                               | `counts`                             |               |                  |         |                                                                            |
 | `successful_deployments`                                  | `counts`                             | `release`     |                  |         | Total successful deployments                                               |
+| `successful_deployments`                                  | `counts_monthly`                     | `release`     |                  |         | Total successful deployments last 28 days                                  |
 | `failed_deployments`                                      | `counts`                             | `release`     |                  |         | Total failed deployments                                                   |
+| `failed_deployments`                                      | `counts_monthly`                     | `release`     |                  |         | Total failed deployments last 28 days                                      |
 | `environments`                                            | `counts`                             | `release`     |                  |         | Total available and stopped environments                                   |
 | `clusters`                                                | `counts`                             | `configure`   |                  |         | Total GitLab Managed clusters both enabled and disabled                    |
 | `clusters_enabled`                                        | `counts`                             | `configure`   |                  |         | Total GitLab Managed clusters currently enabled                            |
diff --git a/lib/gitlab/usage_data.rb b/lib/gitlab/usage_data.rb
index b1953aab4fd6603123a9d365baddd6758265c824..073592797f0eece66a083e23c708d415fb92b7f0 100644
--- a/lib/gitlab/usage_data.rb
+++ b/lib/gitlab/usage_data.rb
@@ -170,6 +170,9 @@ def system_usage_data
       def system_usage_data_monthly
         {
           counts_monthly: {
+            deployments: count(Deployment.where(last_28_days_time_period)),
+            successful_deployments: count(Deployment.success.where(last_28_days_time_period)),
+            failed_deployments: count(Deployment.failed.where(last_28_days_time_period)),
             personal_snippets: count(PersonalSnippet.where(last_28_days_time_period)),
             project_snippets: count(ProjectSnippet.where(last_28_days_time_period))
           }.tap do |data|
diff --git a/spec/factories/deployments.rb b/spec/factories/deployments.rb
index 420464642139d38cfa070a168f8bf9537464d55c..2aab9764560cc92f54743b42cc375ff4c10340e3 100644
--- a/spec/factories/deployments.rb
+++ b/spec/factories/deployments.rb
@@ -7,7 +7,7 @@
     tag { false }
     user { nil }
     project { nil }
-    deployable { association :ci_build, environment: environment.name, project: environment.project }
+    deployable { association :ci_build, environment: environment.name, pipeline: association(:ci_pipeline, project: environment.project) }
     environment factory: :environment
 
     after(:build) do |deployment, evaluator|
diff --git a/spec/factories/usage_data.rb b/spec/factories/usage_data.rb
index dcc0b6acb0c78a446dd1901b4af146ed1fd3306d..92d6e8d306283ddcb8feaf8a013018ad30dbdf8c 100644
--- a/spec/factories/usage_data.rb
+++ b/spec/factories/usage_data.rb
@@ -5,7 +5,8 @@
     skip_create # non-model factories (i.e. without #save)
 
     initialize_with do
-      projects = create_list(:project, 4)
+      projects = create_list(:project, 3)
+      projects << create(:project, :repository)
       create(:board, project: projects[0])
       create(:jira_service, project: projects[0])
       create(:jira_service, :without_properties_callback, project: projects[1])
@@ -91,7 +92,11 @@
       ProjectFeature.first.update_attribute('repository_access_level', 0)
 
       # Create fresh & a month (28-days SMAU) old  data
+      env = create(:environment, project: projects[3])
       [2, 29].each do |n|
+        deployment_options = { created_at: n.days.ago, project: env.project, environment: env }
+        create(:deployment, :failed, deployment_options)
+        create(:deployment, :success, deployment_options)
         create_list(:project_snippet, 2, project: projects[0], created_at: n.days.ago)
         create(:personal_snippet, created_at: n.days.ago)
       end
diff --git a/spec/lib/gitlab/usage_data_spec.rb b/spec/lib/gitlab/usage_data_spec.rb
index 77a2c824fcb9d35c13144f4a7180ec656b4cf255..149db85a9b200b4d70d1309456ea57c7325d1077 100644
--- a/spec/lib/gitlab/usage_data_spec.rb
+++ b/spec/lib/gitlab/usage_data_spec.rb
@@ -130,7 +130,7 @@
       expect(subject[:counts_monthly]).to be_an(Hash)
     end
 
-    it 'gathers projects data correctly' do
+    it 'gathers usage counts correctly' do
       count_data = subject[:counts]
 
       expect(count_data[:projects]).to eq(4)
@@ -188,6 +188,9 @@
       expect(count_data[:clusters_applications_jupyter]).to eq(1)
       expect(count_data[:clusters_management_project]).to eq(1)
 
+      expect(count_data[:deployments]).to eq(4)
+      expect(count_data[:successful_deployments]).to eq(2)
+      expect(count_data[:failed_deployments]).to eq(2)
       expect(count_data[:snippets]).to eq(6)
       expect(count_data[:personal_snippets]).to eq(2)
       expect(count_data[:project_snippets]).to eq(4)
@@ -274,9 +277,12 @@
 
     subject { described_class.system_usage_data_monthly }
 
-    it 'gathers projects data correctly' do
+    it 'gathers monthly usage counts correctly' do
       counts_monthly = subject[:counts_monthly]
 
+      expect(counts_monthly[:deployments]).to eq(2)
+      expect(counts_monthly[:successful_deployments]).to eq(1)
+      expect(counts_monthly[:failed_deployments]).to eq(1)
       expect(counts_monthly[:snippets]).to eq(3)
       expect(counts_monthly[:personal_snippets]).to eq(1)
       expect(counts_monthly[:project_snippets]).to eq(2)