diff --git a/danger/database/Dangerfile b/danger/database/Dangerfile
index 41ca2aa1978031417a776ce7d6b44d0b596eb104..ca4b151faf9759206e926d409f88311293301233 100644
--- a/danger/database/Dangerfile
+++ b/danger/database/Dangerfile
@@ -59,11 +59,9 @@ if gitlab.mr_labels.include?('database') || db_paths_to_review.any?
   markdown(DB_MESSAGE)
   markdown(DB_FILES_MESSAGE + helper.markdown_list(db_paths_to_review)) if db_paths_to_review.any?
 
-  database_labels = helper.missing_database_labels(gitlab.mr_labels)
-
-  if database_labels.any?
+  unless has_database_scoped_labels?(gitlab.mr_labels)
     gitlab.api.update_merge_request(gitlab.mr_json['project_id'],
-                                        gitlab.mr_json['iid'],
-                                        labels: (gitlab.mr_labels + database_labels).join(','))
+                                    gitlab.mr_json['iid'],
+                                    add_labels: 'database::review pending')
   end
 end
diff --git a/danger/documentation/Dangerfile b/danger/documentation/Dangerfile
index 1dd6d484968379973d6bff25a4483fd40df83de0..16d22969fbd9963f8c9b19eb76d9d51d4fd64bb6 100644
--- a/danger/documentation/Dangerfile
+++ b/danger/documentation/Dangerfile
@@ -25,9 +25,3 @@ markdown(<<~MARKDOWN)
   - [Technical Writers assignments](https://about.gitlab.com/handbook/engineering/technical-writing/#designated-technical-writers) for the appropriate technical writer for this review.
   - [Documentation workflows](https://docs.gitlab.com/ee/development/documentation/workflow.html) for information on when to assign a merge request for review.
 MARKDOWN
-
-unless gitlab.mr_labels.include?('documentation')
-  gitlab.api.update_merge_request(gitlab.mr_json['project_id'],
-                                  gitlab.mr_json['iid'],
-                                  labels: (gitlab.mr_labels + ['documentation']).join(','))
-end
diff --git a/danger/specialization_labels/Dangerfile b/danger/specialization_labels/Dangerfile
new file mode 100644
index 0000000000000000000000000000000000000000..b12771b980701d841910aadba39e055008969c1e
--- /dev/null
+++ b/danger/specialization_labels/Dangerfile
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+gitlab_danger = GitlabDanger.new(helper.gitlab_helper)
+
+return unless gitlab_danger.ci?
+
+SPECIALIZATIONS = {
+  database: 'database',
+  backend: 'backend',
+  frontend: 'frontend',
+  docs: 'documentation',
+  qa: 'QA',
+  engineering_productivity: 'Engineering Productivity'
+}.freeze
+
+labels_to_add = helper.changes_by_category.each_with_object([]) do |(category, _changes), memo|
+  label = SPECIALIZATIONS.fetch(category, category.to_s)
+  memo << label unless 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
diff --git a/lib/gitlab/danger/helper.rb b/lib/gitlab/danger/helper.rb
index 9ba5df89a35e75017e6040569ed19f1ad4689755..878f11eb9cec03c82b1e9f835d1daaaa24feac20 100644
--- a/lib/gitlab/danger/helper.rb
+++ b/lib/gitlab/danger/helper.rb
@@ -206,16 +206,6 @@ def new_teammates(usernames)
         usernames.map { |u| Gitlab::Danger::Teammate.new('username' => u) }
       end
 
-      def missing_database_labels(current_mr_labels)
-        labels = if has_database_scoped_labels?(current_mr_labels)
-                   ['database']
-                 else
-                   ['database', 'database::review pending']
-                 end
-
-        labels - current_mr_labels
-      end
-
       def sanitize_mr_title(title)
         title.gsub(DRAFT_REGEX, '').gsub(/`/, '\\\`')
       end
@@ -259,8 +249,6 @@ def changed_files(regex)
         all_changed_files.grep(regex)
       end
 
-      private
-
       def has_database_scoped_labels?(current_mr_labels)
         current_mr_labels.any? { |label| label.start_with?('database::') }
       end
diff --git a/lib/gitlab_danger.rb b/lib/gitlab_danger.rb
index a98ac9200da90aa3dd3c79e9abf84409d660fb54..5537bd81f10e03da50d106ce8c62028c8b7521cf 100644
--- a/lib/gitlab_danger.rb
+++ b/lib/gitlab_danger.rb
@@ -22,6 +22,7 @@ class GitlabDanger
     roulette
     ce_ee_vue_templates
     sidekiq_queues
+    specialization_labels
   ].freeze
 
   MESSAGE_PREFIX = '==>'.freeze
diff --git a/spec/lib/gitlab/danger/helper_spec.rb b/spec/lib/gitlab/danger/helper_spec.rb
index e5018e46634a2c449b334c5f3d511463980c1f9a..0e66bf8691e471c2255663d0876b4d4ed44f0e11 100644
--- a/spec/lib/gitlab/danger/helper_spec.rb
+++ b/spec/lib/gitlab/danger/helper_spec.rb
@@ -371,22 +371,6 @@
     end
   end
 
-  describe '#missing_database_labels' do
-    subject { helper.missing_database_labels(current_mr_labels) }
-
-    context 'when current merge request has ~database::review pending' do
-      let(:current_mr_labels) { ['database::review pending', 'feature'] }
-
-      it { is_expected.to match_array(['database']) }
-    end
-
-    context 'when current merge request does not have ~database::review pending' do
-      let(:current_mr_labels) { ['feature'] }
-
-      it { is_expected.to match_array(['database', 'database::review pending']) }
-    end
-  end
-
   describe '#sanitize_mr_title' do
     where(:mr_title, :expected_mr_title) do
       'My MR title'      | 'My MR title'