diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb
index 623fd917afff20100670213e277c1a35806cd16e..8566a77df3236adc2b764fb6645282e1a0f6c6d8 100644
--- a/app/controllers/admin/users_controller.rb
+++ b/app/controllers/admin/users_controller.rb
@@ -148,7 +148,8 @@ def ban
     if result[:status] == :success
       redirect_back_or_admin_user(notice: _("Successfully banned"))
     else
-      redirect_back_or_admin_user(alert: _("Error occurred. User was not banned"))
+      alert = format(_("Error occurred. %{message}"), message: result[:message])
+      redirect_back_or_admin_user(alert: alert)
     end
   end
 
diff --git a/ee/app/services/ee/users/ban_service.rb b/ee/app/services/ee/users/ban_service.rb
index 41892d6ed497eaff2919b2249f6ea1d73c97c71d..77f610a89adfa0aaf9410764516f8ff81ea8c6c6 100644
--- a/ee/app/services/ee/users/ban_service.rb
+++ b/ee/app/services/ee/users/ban_service.rb
@@ -4,6 +4,7 @@ module EE
   module Users
     module BanService
       extend ::Gitlab::Utils::Override
+      include ::Gitlab::Utils::StrongMemoize
       include ManagementBaseService
 
       private
@@ -15,6 +16,26 @@ def event_name
       def event_message
         'Banned user'
       end
+
+      def paid_user?(user)
+        strong_memoize_with(:paid_user, user) do
+          user.enterprise_user? || user.belongs_to_paid_namespace?(exclude_trials: true)
+        end
+      end
+
+      override :valid_state?
+      def valid_state?(user)
+        return false if paid_user?(user)
+
+        super
+      end
+
+      override :state_error
+      def state_error(user)
+        return error(_("You cannot ban paid users."), :forbidden) if paid_user?(user)
+
+        super
+      end
     end
   end
 end
diff --git a/ee/spec/services/ee/users/ban_service_spec.rb b/ee/spec/services/ee/users/ban_service_spec.rb
index 666f022c6fe690cc9a88f766607a1448af3b6942..8d89252f849eae3e338089ae211a360af9c7cdab 100644
--- a/ee/spec/services/ee/users/ban_service_spec.rb
+++ b/ee/spec/services/ee/users/ban_service_spec.rb
@@ -7,12 +7,12 @@
 
   subject(:service) { described_class.new(current_user) }
 
-  describe '#execute' do
-    let!(:user) { create(:user) }
+  describe '#execute', :enable_admin_mode do
+    let_it_be_with_reload(:user) { create(:user) }
 
     subject(:operation) { service.execute(user) }
 
-    context 'for audit events', :enable_admin_mode do
+    context 'for audit events' do
       include_examples 'audit event logging' do
         let(:operation) { service.execute(user) }
 
@@ -38,5 +38,51 @@
         end
       end
     end
+
+    context 'for paid users', :saas do
+      shared_examples 'not banning paid users' do
+        specify :aggregate_failures do
+          response = service.execute(user)
+
+          expect(response[:status]).to eq(:error)
+          expect(response[:message]).to match('You cannot ban paid users.')
+          expect(user).not_to be_banned
+        end
+      end
+
+      context 'when the user is part of a paid namespace' do
+        before do
+          create(:group_with_plan, plan: :ultimate_plan, owners: user)
+        end
+
+        it_behaves_like 'not banning paid users'
+      end
+
+      context 'when the user is an enterprise user' do
+        let_it_be(:user) { create(:enterprise_user) }
+
+        it_behaves_like 'not banning paid users'
+      end
+
+      context 'when the user is a member of a trial namespace' do
+        before do
+          create(
+            :group_with_plan,
+            plan: :ultimate_trial_plan,
+            trial: true,
+            trial_starts_on: Date.current,
+            trial_ends_on: 30.days.from_now,
+            owners: user
+          )
+        end
+
+        it 'bans the user', :aggregate_failures do
+          response = service.execute(user)
+
+          expect(response[:status]).to eq(:success)
+          expect(user).to be_banned
+        end
+      end
+    end
   end
 end
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index ada561c740ee7a84b7b9025fd600730ff9b2ff2d..a66fa25e53b056beb6cccc4c515112e1757a2b1f 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -23700,13 +23700,13 @@ msgstr ""
 msgid "Error occurred while updating the issue status"
 msgstr ""
 
-msgid "Error occurred. A blocked user cannot be deactivated"
+msgid "Error occurred. %{message}"
 msgstr ""
 
-msgid "Error occurred. A blocked user must be unblocked to be activated"
+msgid "Error occurred. A blocked user cannot be deactivated"
 msgstr ""
 
-msgid "Error occurred. User was not banned"
+msgid "Error occurred. A blocked user must be unblocked to be activated"
 msgstr ""
 
 msgid "Error occurred. User was not blocked"
@@ -67497,6 +67497,9 @@ msgstr ""
 msgid "You cannot assign or unassign frameworks to a project that has more than one associated framework."
 msgstr ""
 
+msgid "You cannot ban paid users."
+msgstr ""
+
 msgid "You cannot change the access of the last owner from the organization"
 msgstr ""
 
diff --git a/spec/controllers/admin/users_controller_spec.rb b/spec/controllers/admin/users_controller_spec.rb
index 1e0e69b4b9f0489dda9a0467697546005296448a..7e1c721eed63910419e22c325f5b4bbbc7838b8c 100644
--- a/spec/controllers/admin/users_controller_spec.rb
+++ b/spec/controllers/admin/users_controller_spec.rb
@@ -509,7 +509,7 @@
 
         user.reload
         expect(user.banned?).to be_falsey
-        expect(flash[:alert]).to eq _('Error occurred. User was not banned')
+        expect(flash[:alert]).to eq _('Error occurred. You cannot ban blocked users.')
       end
     end
   end