diff --git a/app/assets/javascripts/header.js b/app/assets/javascripts/header.js
index 1678991b1eaa3d6abcfc5310a2e28871ed942403..67b068f1c6b07e84c86f0ba0f72f2e2e06ae3d24 100644
--- a/app/assets/javascripts/header.js
+++ b/app/assets/javascripts/header.js
@@ -74,20 +74,27 @@ function initStatusTriggers() {
   }
 }
 
+function trackShowUserDropdownLink(trackEvent, elToTrack, el) {
+  const { trackLabel, trackProperty } = elToTrack.dataset;
+
+  $(el).on('shown.bs.dropdown', () => {
+    Tracking.event(document.body.dataset.page, trackEvent, {
+      label: trackLabel,
+      property: trackProperty,
+    });
+  });
+}
 export function initNavUserDropdownTracking() {
   const el = document.querySelector('.js-nav-user-dropdown');
   const buyEl = document.querySelector('.js-buy-ci-minutes-link');
+  const upgradeEl = document.querySelector('.js-upgrade-plan-link');
 
   if (el && buyEl) {
-    const { trackLabel, trackProperty } = buyEl.dataset;
-    const trackEvent = 'show_buy_ci_minutes';
+    trackShowUserDropdownLink('show_buy_ci_minutes', buyEl, el);
+  }
 
-    $(el).on('shown.bs.dropdown', () => {
-      Tracking.event(undefined, trackEvent, {
-        label: trackLabel,
-        property: trackProperty,
-      });
-    });
+  if (el && upgradeEl) {
+    trackShowUserDropdownLink('show_upgrade_link', upgradeEl, el);
   }
 }
 
diff --git a/app/assets/stylesheets/framework/header.scss b/app/assets/stylesheets/framework/header.scss
index a0a020ec548435a43653b24e77a28b91a5799b38..2c7e9428ef1a40d48750e3b70df8b660d910eb5d 100644
--- a/app/assets/stylesheets/framework/header.scss
+++ b/app/assets/stylesheets/framework/header.scss
@@ -553,6 +553,7 @@
       vertical-align: text-top;
     }
 
+    a.upgrade-plan-link gl-emoji,
     a.ci-minutes-emoji gl-emoji,
     a.trial-link gl-emoji {
       font-size: $gl-font-size;
diff --git a/app/views/layouts/header/_current_user_dropdown.html.haml b/app/views/layouts/header/_current_user_dropdown.html.haml
index 410b120396db3b310e60dc63280c1f300ebc21f2..7d9924719a2b231a1887505c5b384a491f4ed0d1 100644
--- a/app/views/layouts/header/_current_user_dropdown.html.haml
+++ b/app/views/layouts/header/_current_user_dropdown.html.haml
@@ -27,6 +27,7 @@
     %li
       = link_to s_("CurrentUser|Settings"), profile_path, data: { qa_selector: 'settings_link' }
   = render_if_exists 'layouts/header/buy_ci_minutes', project: @project, namespace: @group
+  = render_if_exists 'layouts/header/upgrade'
 
   - if current_user_menu?(:help)
     %li.divider.d-md-none
diff --git a/ee/app/helpers/ee/users_helper.rb b/ee/app/helpers/ee/users_helper.rb
index 763577bdfcfe0e2206c5d4b0c23e1d52d7ee1c2c..7631b3a162ee32a9d5e6a969d75e52ce52b0da5f 100644
--- a/ee/app/helpers/ee/users_helper.rb
+++ b/ee/app/helpers/ee/users_helper.rb
@@ -20,6 +20,16 @@ def user_badges_in_admin_section(user)
       end
     end
 
+    def show_upgrade_link?(user)
+      return unless user
+      return unless ::Gitlab.com?
+      return unless experiment_enabled?(:upgrade_link_in_user_menu_a)
+
+      Rails.cache.fetch(['users', user.id, 'show_upgrade_link?'], expires_in: 10.minutes) do
+        user.owns_upgradeable_namespace?
+      end
+    end
+
     private
 
     def trials_allowed?(user)
diff --git a/ee/app/models/ee/user.rb b/ee/app/models/ee/user.rb
index e85d2892e2c024c25ceaedc248e2f3f90f8317cb..e8b290ba60df558a422110defd1cec7e410639da 100644
--- a/ee/app/models/ee/user.rb
+++ b/ee/app/models/ee/user.rb
@@ -243,17 +243,17 @@ def has_paid_namespace?
       ::Namespace
         .from("(#{namespace_union_for_reporter_developer_maintainer_owned}) #{::Namespace.table_name}")
         .include_gitlab_subscription
-        .where(gitlab_subscriptions: { hosted_plan: ::Plan.where(name: Plan::PAID_HOSTED_PLANS) })
+        .where(gitlab_subscriptions: { hosted_plan: ::Plan.where(name: ::Plan::PAID_HOSTED_PLANS) })
         .any?
     end
 
     # Returns true if the user is an Owner on any namespace currently on
     # a paid plan
-    def owns_paid_namespace?
+    def owns_paid_namespace?(plans: ::Plan::PAID_HOSTED_PLANS)
       ::Namespace
         .from("(#{namespace_union_for_owned}) #{::Namespace.table_name}")
         .include_gitlab_subscription
-        .where(gitlab_subscriptions: { hosted_plan: ::Plan.where(name: Plan::PAID_HOSTED_PLANS) })
+        .where(gitlab_subscriptions: { hosted_plan: ::Plan.where(name: plans) })
         .any?
     end
 
@@ -363,6 +363,11 @@ def security_dashboard
       InstanceSecurityDashboard.new(self)
     end
 
+    def owns_upgradeable_namespace?
+      !owns_paid_namespace?(plans: [::Plan::GOLD]) &&
+        owns_paid_namespace?(plans: [::Plan::BRONZE, ::Plan::SILVER])
+    end
+
     protected
 
     override :password_required?
diff --git a/ee/app/views/layouts/header/_upgrade.html.haml b/ee/app/views/layouts/header/_upgrade.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..356caa72d5f9aaa108d6b84dda80eabb2377d56e
--- /dev/null
+++ b/ee/app/views/layouts/header/_upgrade.html.haml
@@ -0,0 +1,7 @@
+- if show_upgrade_link?(current_user)
+  %li
+    = link_to EE::SUBSCRIPTIONS_PLANS_URL,
+      class: 'upgrade-plan-link js-upgrade-plan-link',
+      data: { 'track-event': 'click_upgrade_link', 'track-label': current_user.namespace.actual_plan_name, 'track-property': 'user_dropdown' } do
+      = s_("CurrentUser|Upgrade")
+      = emoji_icon('rocket', 'aria-hidden': true)
diff --git a/ee/spec/models/user_spec.rb b/ee/spec/models/user_spec.rb
index accec07137676c00f0c575c83469b40790fd7929..ca3ab2cd152d14d01599bafb27f35174301047cf 100644
--- a/ee/spec/models/user_spec.rb
+++ b/ee/spec/models/user_spec.rb
@@ -1204,4 +1204,49 @@
       expect(security_dashboard).to be_a(InstanceSecurityDashboard)
     end
   end
+
+  describe '#owns_upgradeable_namespace?' do
+    let_it_be(:user) { create(:user) }
+
+    subject { user.owns_upgradeable_namespace? }
+
+    using RSpec::Parameterized::TableSyntax
+
+    where(:hosted_plan, :result) do
+      :bronze_plan    | true
+      :silver_plan    | true
+      :gold_plan      | false
+      :free_plan      | false
+      :default_plan   | false
+    end
+
+    with_them do
+      it 'returns the correct result for each plan on a personal namespace' do
+        plan = create(hosted_plan)
+        create(:gitlab_subscription, namespace: user.namespace, hosted_plan: plan)
+
+        expect(subject).to be result
+      end
+
+      it 'returns the correct result for each plan on a group owned by the user' do
+        create(:group_with_plan, plan: hosted_plan).add_owner(user)
+
+        expect(subject).to be result
+      end
+    end
+
+    it 'returns false when there is no subscription for the personal namespace' do
+      expect(subject).to be false
+    end
+
+    it 'returns false when the user has multiple groups and any group has gold' do
+      create(:group_with_plan, plan: :bronze_plan).add_owner(user)
+      create(:group_with_plan, plan: :silver_plan).add_owner(user)
+      create(:group_with_plan, plan: :gold_plan).add_owner(user)
+
+      user.namespace.plans.reload
+
+      expect(subject).to be false
+    end
+  end
 end
diff --git a/ee/spec/views/layouts/header/_current_user_dropdown.html.haml_spec.rb b/ee/spec/views/layouts/header/_current_user_dropdown.html.haml_spec.rb
index 2debe4d7abb2adc57cad099039639f8d82964787..f6bd8ca6a37ed7f752e122fc00146a3b9494f166 100644
--- a/ee/spec/views/layouts/header/_current_user_dropdown.html.haml_spec.rb
+++ b/ee/spec/views/layouts/header/_current_user_dropdown.html.haml_spec.rb
@@ -4,31 +4,63 @@
 
 describe 'layouts/header/_current_user_dropdown' do
   let_it_be(:user) { create(:user) }
-  let(:need_minutes) { true }
 
-  before do
-    allow(view).to receive(:current_user).and_return(user)
-    allow(view).to receive(:show_buy_ci_minutes?).and_return(need_minutes)
+  describe 'Buy CI Minutes link in user dropdown' do
+    let(:need_minutes) { true }
 
-    render
-  end
+    before do
+      allow(view).to receive(:current_user).and_return(user)
+      allow(view).to receive(:show_upgrade_link?).and_return(false)
+      allow(view).to receive(:show_buy_ci_minutes?).and_return(need_minutes)
+
+      render
+    end
 
-  subject { rendered }
+    subject { rendered }
 
-  context 'when ci minutes need bought' do
-    it 'has "Buy CI minutes" link with correct data properties', :aggregate_failures do
-      expect(subject).to have_selector('[data-track-event="click_buy_ci_minutes"]')
-      expect(subject).to have_selector("[data-track-label='#{user.namespace.actual_plan_name}']")
-      expect(subject).to have_selector('[data-track-property="user_dropdown"]')
-      expect(subject).to have_link('Buy CI minutes')
+    context 'when ci minutes need bought' do
+      it 'has "Buy CI minutes" link with correct data properties', :aggregate_failures do
+        expect(subject).to have_selector('[data-track-event="click_buy_ci_minutes"]')
+        expect(subject).to have_selector("[data-track-label='#{user.namespace.actual_plan_name}']")
+        expect(subject).to have_selector('[data-track-property="user_dropdown"]')
+        expect(subject).to have_link('Buy CI minutes')
+      end
+    end
+
+    context 'when ci minutes do not need bought' do
+      let(:need_minutes) { false }
+
+      it 'has no "Buy CI minutes" link' do
+        expect(subject).not_to have_link('Buy CI minutes')
+      end
     end
   end
 
-  context 'when ci minutes do not need bought' do
-    let(:need_minutes) { false }
+  describe 'Upgrade link in user dropdown' do
+    let(:on_upgradeable_plan) { true }
+
+    before do
+      allow(view).to receive(:current_user).and_return(user)
+      allow(view).to receive(:show_buy_ci_minutes?).and_return(false)
+      allow(view).to receive(:show_upgrade_link?).and_return(on_upgradeable_plan)
+
+      render
+    end
+
+    subject { rendered }
+
+    context 'when user is on an upgradeable plan' do
+      it 'displays the Upgrade link' do
+        expect(subject).to have_link('Upgrade')
+      end
+    end
+
+    context 'when user is not on an upgradeable plan' do
+      let(:on_upgradeable_plan) { false }
 
-    it 'has no "Buy CI minutes" link' do
-      expect(subject).not_to have_link('Buy CI minutes')
+      it 'does not display the Upgrade link' do
+        expect(subject).not_to have_link('Upgrade')
+      end
     end
   end
 end
diff --git a/lib/gitlab/experimentation.rb b/lib/gitlab/experimentation.rb
index 0097961eed4515ee09af375a7827232b901920ab..3495b4a0b725f47201a57894b46c900b6ea749fc 100644
--- a/lib/gitlab/experimentation.rb
+++ b/lib/gitlab/experimentation.rb
@@ -42,6 +42,9 @@ module Experimentation
       },
       buy_ci_minutes_version_a: {
         tracking_category: 'Growth::Expansion::Experiment::BuyCiMinutesVersionA'
+      },
+      upgrade_link_in_user_menu_a: {
+        tracking_category: 'Growth::Expansion::Experiment::UpgradeLinkInUserMenuA'
       }
     }.freeze
 
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index ae4c454208be146d0894abaac3edd90c578c8979..50c131c991b45514a75ea7a27b7a72ecbfe09bda 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -6477,6 +6477,9 @@ msgstr ""
 msgid "CurrentUser|Start a Gold trial"
 msgstr ""
 
+msgid "CurrentUser|Upgrade"
+msgstr ""
+
 msgid "Custom CI configuration path"
 msgstr ""
 
diff --git a/spec/frontend/header_spec.js b/spec/frontend/header_spec.js
index 0a74799283a1627c6c2202a4d2b02b775aacceab..6d2d7976196afe3ed4c1070ac2f127c075acc9eb 100644
--- a/spec/frontend/header_spec.js
+++ b/spec/frontend/header_spec.js
@@ -60,8 +60,8 @@ describe('Header', () => {
     beforeEach(() => {
       setFixtures(`
       <li class="js-nav-user-dropdown">
-        <a class="js-buy-ci-minutes-link" data-track-event="click_buy_ci_minutes" data-track-label="free" data-track-property="user_dropdown">Buy CI minutes
-        </a>
+        <a class="js-buy-ci-minutes-link" data-track-event="click_buy_ci_minutes" data-track-label="free" data-track-property="user_dropdown">Buy CI minutes</a>
+        <a class="js-upgrade-plan-link" data-track-event="click_upgrade_link" data-track-label="free" data-track-property="user_dropdown">Upgrade</a>
       </li>`);
 
       trackingSpy = mockTracking('_category_', $('.js-nav-user-dropdown').element, jest.spyOn);
@@ -77,8 +77,16 @@ describe('Header', () => {
     it('sends a tracking event when the dropdown is opened and contains Buy CI minutes link', () => {
       $('.js-nav-user-dropdown').trigger('shown.bs.dropdown');
 
-      expect(trackingSpy).toHaveBeenCalledTimes(1);
-      expect(trackingSpy).toHaveBeenCalledWith(undefined, 'show_buy_ci_minutes', {
+      expect(trackingSpy).toHaveBeenCalledWith('some:page', 'show_buy_ci_minutes', {
+        label: 'free',
+        property: 'user_dropdown',
+      });
+    });
+
+    it('sends a tracking event when the dropdown is opened and contains Upgrade link', () => {
+      $('.js-nav-user-dropdown').trigger('shown.bs.dropdown');
+
+      expect(trackingSpy).toHaveBeenCalledWith('some:page', 'show_upgrade_link', {
         label: 'free',
         property: 'user_dropdown',
       });