diff --git a/Dangerfile b/Dangerfile
index 37a45674e16856fed64a107205fe7e748d43a9b7..ab96c43c4e55d4e232b58f6c05bb1a14625f049f 100644
--- a/Dangerfile
+++ b/Dangerfile
@@ -17,6 +17,14 @@ end
 
 anything_to_post = status_report.values.any? { |data| data.any? }
 
-if helper.ci? && anything_to_post
+return unless helper.ci?
+
+if project_helper.labels_to_add.any?
+  gitlab.api.update_merge_request(gitlab.mr_json['project_id'],
+                                  gitlab.mr_json['iid'],
+                                  add_labels: project_helper.labels_to_add.join(','))
+end
+
+if anything_to_post
   markdown("**If needed, you can retry the [`danger-review` job](#{ENV['CI_JOB_URL']}) that generated this comment.**")
 end
diff --git a/danger/database/Dangerfile b/danger/database/Dangerfile
index 693c03b9daddd18e22123127762d767fa71da07b..70adbb4c13990a685c4f3f7ea2fd889e890ab670 100644
--- a/danger/database/Dangerfile
+++ b/danger/database/Dangerfile
@@ -66,8 +66,6 @@ if gitlab.mr_labels.include?('database') || db_paths_to_review.any?
   end
 
   unless helper.has_database_scoped_labels?
-    gitlab.api.update_merge_request(gitlab.mr_json['project_id'],
-                                    gitlab.mr_json['iid'],
-                                    add_labels: 'database::review pending')
+    project_helper.labels_to_add << 'database::review pending'
   end
 end
diff --git a/danger/feature_flag/Dangerfile b/danger/feature_flag/Dangerfile
index 9b67590f1172ac9e1481f5b1d3159ebf1fec7799..d6c1c53cddcb0959ebd0078939c9e3262b22b0df 100644
--- a/danger/feature_flag/Dangerfile
+++ b/danger/feature_flag/Dangerfile
@@ -58,9 +58,7 @@ def message_for_feature_flag_with_group!(feature_flag:, mr_group_label:)
   return if feature_flag.group_match_mr_label?(mr_group_label)
 
   if mr_group_label.nil?
-    gitlab.api.update_merge_request(gitlab.mr_json['project_id'],
-                                    gitlab.mr_json['iid'],
-                                    add_labels: feature_flag.group)
+    project_helper.labels_to_add << feature_flag.group
   else
     fail %(`group` is set to ~"#{feature_flag.group}" in #{gitlab.html_link(feature_flag.path)}, which does not match ~"#{mr_group_label}" set on the MR!)
   end
diff --git a/danger/product_intelligence/Dangerfile b/danger/product_intelligence/Dangerfile
index dda3fbfc58905ea61ddc7ad23e257cfaafdbef38..eedb9b89d2254b4240e1afbda45bcc52c0f4facb 100644
--- a/danger/product_intelligence/Dangerfile
+++ b/danger/product_intelligence/Dangerfile
@@ -13,12 +13,10 @@ MSG
 
 # exit if not matching files or if no product intelligence labels
 product_intelligence_paths_to_review = project_helper.changes_by_category[:product_intelligence]
-labels = product_intelligence.missing_labels
+labels_to_add = product_intelligence.missing_labels
 
-return if product_intelligence_paths_to_review.empty? || labels.empty?
+return if product_intelligence_paths_to_review.empty? || labels_to_add.empty?
 
 warn format(CHANGED_FILES_MESSAGE, changed_files: helper.markdown_list(product_intelligence_paths_to_review))
 
-gitlab.api.update_merge_request(gitlab.mr_json['project_id'],
-                                    gitlab.mr_json['iid'],
-                                    add_labels: labels)
+project_helper.labels_to_add.concat(labels_to_add)
diff --git a/danger/specialization_labels/Dangerfile b/danger/specialization_labels/Dangerfile
index e42e17762e468a3751eead95ab23ecdf23e48799..ec79611d93d8b76a817f0e9ead851f98ec03b981 100644
--- a/danger/specialization_labels/Dangerfile
+++ b/danger/specialization_labels/Dangerfile
@@ -19,8 +19,4 @@ labels_to_add = project_helper.changes_by_category.each_with_object([]) do |(cat
   memo << label if label && !gitlab.mr_labels.include?(label)
 end
 
-if labels_to_add.any?
-  gitlab.api.update_merge_request(gitlab.mr_json['project_id'],
-                                  gitlab.mr_json['iid'],
-                                  add_labels: labels_to_add.join(','))
-end
+project_helper.labels_to_add.concat(labels_to_add) if labels_to_add.any?
diff --git a/danger/metadata/Dangerfile b/danger/z_metadata/Dangerfile
similarity index 94%
rename from danger/metadata/Dangerfile
rename to danger/z_metadata/Dangerfile
index 537f55ed649ce3c1c83f089ec301af92cbde6882..0a70554486f77b9a749d21086ae38f973a8890cf 100644
--- a/danger/metadata/Dangerfile
+++ b/danger/z_metadata/Dangerfile
@@ -18,7 +18,7 @@ if gitlab.mr_body.size < 5
   fail "Please provide a proper merge request description."
 end
 
-if (TYPE_LABELS & gitlab.mr_labels).empty?
+if (TYPE_LABELS & (gitlab.mr_labels + project_helper.labels_to_add)).empty?
   warn 'Please add a [merge request type](https://about.gitlab.com/handbook/engineering/metrics/#work-type-classification) to this merge request.'
 end
 
diff --git a/doc/development/dangerbot.md b/doc/development/dangerbot.md
index aca37e2182a6583025e79b13c5e46ca9eaffd253..829f6af76be3aaba2a8226a0b66e613c8163a01e 100644
--- a/doc/development/dangerbot.md
+++ b/doc/development/dangerbot.md
@@ -118,6 +118,23 @@ However, you can speed these cycles up somewhat by emptying the
 `.gitlab/ci/rails.gitlab-ci.yml` file in your merge request. Just don't forget
 to revert the change before merging!
 
+#### Adding labels via Danger
+
+NOTE:
+This is currently applicable to the [`gitlab-org/gitlab`](https://gitlab.com/gitlab-org/gitlab)
+project only.
+
+Danger is often used to improve MR hygiene by adding labels. Instead of calling the
+API directly in your `Dangerfile`, add the labels to the `project_helper.labels_to_add` array.
+The main `Dangerfile` will then take care of adding the labels to the MR with a single API call.
+
+#### Shared rules and plugins
+
+If the rule or plugin you implement can be useful for other projects, think about
+upstreaming them to the [`gitlab-org/gitlab-dangerfiles`](https://gitlab.com/gitlab-org/gitlab-dangerfiles) project.
+
+#### Enable Danger on a project
+
 To enable the Dangerfile on another existing GitLab project, run the following
 extra steps:
 
diff --git a/tooling/danger/project_helper.rb b/tooling/danger/project_helper.rb
index 1eac7380b346062c60e4cc9cbd2b9c1d692f387c..329599f338105d13a64732292903a1fcdbc82206 100644
--- a/tooling/danger/project_helper.rb
+++ b/tooling/danger/project_helper.rb
@@ -22,12 +22,12 @@ module ProjectHelper
         ce_ee_vue_templates
         ci_templates
         datateam
-        metadata
         feature_flag
         roulette
         sidekiq_queues
         specialization_labels
         specs
+        z_metadata
       ].freeze
 
       MESSAGE_PREFIX = '==>'
@@ -189,6 +189,10 @@ def file_lines(filename)
         read_file(filename).lines(chomp: true)
       end
 
+      def labels_to_add
+        @labels_to_add ||= []
+      end
+
       private
 
       def read_file(filename)