diff --git a/app/views/admin/users/_tabs.html.haml b/app/views/admin/users/_tabs.html.haml
index fa038426b690590c6be075bbf4e12626403c0564..3c95723479767bef8a110a030f43b4f5b164e507 100644
--- a/app/views/admin/users/_tabs.html.haml
+++ b/app/views/admin/users/_tabs.html.haml
@@ -1,3 +1,4 @@
 = gl_tabs_nav({ class: 'gl-flex-grow-1 gl-border-0', data: { testid: 'admin-users-tabs' } }) do
   = gl_tab_link_to s_('AdminUsers|Users'), admin_users_path
+  = render_if_exists 'admin/users/role_promotion_requests_tab'
   = gl_tab_link_to s_('AdminUsers|Cohorts'), admin_cohorts_path
diff --git a/ee/app/controllers/admin/role_promotion_requests_controller.rb b/ee/app/controllers/admin/role_promotion_requests_controller.rb
new file mode 100644
index 0000000000000000000000000000000000000000..887b1c2fc29cb6741ce4642a308488de8d1b7737
--- /dev/null
+++ b/ee/app/controllers/admin/role_promotion_requests_controller.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+module Admin
+  class RolePromotionRequestsController < Admin::ApplicationController
+    include ::MemberManagement::PromotionManagementUtils
+
+    feature_category :seat_cost_management
+    before_action :verify_role_promotion_requests_enabled!
+
+    def index; end
+
+    private
+
+    def verify_role_promotion_requests_enabled!
+      render_404 unless promotion_management_applicable?
+    end
+  end
+end
diff --git a/ee/app/helpers/gitlab_subscriptions/promotion_management_helper.rb b/ee/app/helpers/gitlab_subscriptions/promotion_management_helper.rb
new file mode 100644
index 0000000000000000000000000000000000000000..f4d9ef05b47d0fe99fff161740196f561117a6e7
--- /dev/null
+++ b/ee/app/helpers/gitlab_subscriptions/promotion_management_helper.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+module GitlabSubscriptions
+  module PromotionManagementHelper
+    include ::MemberManagement::PromotionManagementUtils
+  end
+end
diff --git a/ee/app/views/admin/role_promotion_requests/_role_promotion_requests.html.haml b/ee/app/views/admin/role_promotion_requests/_role_promotion_requests.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..07a7210bdb5cebd1038eeb7f9fffb4882b5a3a94
--- /dev/null
+++ b/ee/app/views/admin/role_promotion_requests/_role_promotion_requests.html.haml
@@ -0,0 +1,2 @@
+#js-admin-users-role-promotion-requests-app{ data: admin_users_data_attributes(@users) }
+  = render Pajamas::SpinnerComponent.new(size: :lg, class: 'gl-my-7')
diff --git a/ee/app/views/admin/role_promotion_requests/index.html.haml b/ee/app/views/admin/role_promotion_requests/index.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..ee030a4a232168e068bf18f0ea15067dcca7206f
--- /dev/null
+++ b/ee/app/views/admin/role_promotion_requests/index.html.haml
@@ -0,0 +1,7 @@
+- page_title _("Users")
+
+= render 'admin/users/tabs'
+
+.tab-content
+  .tab-pane.active
+    = render 'role_promotion_requests'
diff --git a/ee/app/views/admin/users/_role_promotion_requests_tab.haml b/ee/app/views/admin/users/_role_promotion_requests_tab.haml
new file mode 100644
index 0000000000000000000000000000000000000000..01f1da13356f93bd5a96ad07b6c444d0d65771fe
--- /dev/null
+++ b/ee/app/views/admin/users/_role_promotion_requests_tab.haml
@@ -0,0 +1,2 @@
+- if promotion_management_applicable?
+  = gl_tab_link_to s_('AdminUsers|Role Promotions'), admin_role_promotion_requests_path
diff --git a/ee/config/routes/admin.rb b/ee/config/routes/admin.rb
index 1feba56890f0303c9d6fd9d2caab98ea2c257e47..d9c3f67bc4f566af06fae72449abc5c5bea3b5e1 100644
--- a/ee/config/routes/admin.rb
+++ b/ee/config/routes/admin.rb
@@ -43,6 +43,7 @@
   end
 
   resource :subscription, only: [:show]
+  resources :role_promotion_requests, only: :index
 
   get 'code_suggestions', to: 'code_suggestions#index'
 
diff --git a/ee/spec/controllers/admin/role_promotion_requests_controller_spec.rb b/ee/spec/controllers/admin/role_promotion_requests_controller_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..2cf7ca3589edab458fb50734c12f3d7c0bbab794
--- /dev/null
+++ b/ee/spec/controllers/admin/role_promotion_requests_controller_spec.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Admin::RolePromotionRequestsController, feature_category: :seat_cost_management do
+  let(:admin) { create(:admin) }
+
+  let_it_be(:license) { create(:license, plan: License::ULTIMATE_PLAN) }
+  let(:feature_flag) { true }
+  let(:feature_settings) { true }
+
+  before do
+    stub_feature_flags(member_promotion_management: feature_flag)
+    stub_application_setting(enable_member_promotion_management: feature_settings)
+    allow(License).to receive(:current).and_return(license)
+    sign_in(admin)
+  end
+
+  describe 'GET #index' do
+    context 'when member promotion management is enabled' do
+      it 'renders the show template' do
+        get :index
+
+        expect(response).to have_gitlab_http_status(:ok)
+        expect(response).to render_template('index')
+      end
+    end
+
+    context 'when member promotion management is disabled' do
+      let(:feature_settings) { false }
+
+      it 'returns 404' do
+        get :index
+
+        expect(response).to have_gitlab_http_status(:not_found)
+      end
+    end
+  end
+end
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index ece506571f79f38ebfedec26afa352033a738bc8..05b577bfc4969c778305f023193b1fa6110493a7 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -4325,6 +4325,9 @@ msgstr ""
 msgid "AdminUsers|Restore user access to the account, including web, Git and API."
 msgstr ""
 
+msgid "AdminUsers|Role Promotions"
+msgstr ""
+
 msgid "AdminUsers|Search by name, email, or username"
 msgstr ""