diff --git a/app/controllers/autocomplete_controller.rb b/app/controllers/autocomplete_controller.rb
index 1c2bd10bc8143dd979ed9a997aef4b429f405d7c..3536205daeacb652d7e0e84bb6c2ca870f901b00 100644
--- a/app/controllers/autocomplete_controller.rb
+++ b/app/controllers/autocomplete_controller.rb
@@ -6,7 +6,8 @@ class AutocompleteController < ApplicationController
   skip_before_action :authenticate_user!, only: [
     :users, :award_emojis, :merge_request_target_branches, :merge_request_source_branches
   ]
-  before_action :check_search_rate_limit!, only: [:users, :projects]
+  before_action :check_search_rate_limit!, only: :projects
+  before_action :check_autocomplete_users_rate_limit!, only: :users
 
   feature_category :user_profile, [:users, :user]
   feature_category :groups_and_projects, [:projects]
@@ -112,6 +113,16 @@ def merge_request_branches(source: false, target: false)
       render json: { error: _('At least one of group_id or project_id must be specified') }, status: :bad_request
     end
   end
+
+  def check_autocomplete_users_rate_limit!
+    return check_search_rate_limit! if Feature.disabled?(:autocomplete_users_rate_limit) # rubocop:disable Gitlab/FeatureFlagWithoutActor -- cannot scope to user as it needs to handle unauthenticated requests
+
+    if current_user
+      check_rate_limit!(:autocomplete_users, scope: current_user)
+    else
+      check_rate_limit!(:autocomplete_users_unauthenticated, scope: request.ip)
+    end
+  end
 end
 
 AutocompleteController.prepend_mod_with('AutocompleteController')
diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb
index 4db587b6649ae485ee5fd6bcacba14513abea881..ceb3e38668622b838b425ada839aaca43b8b7064 100644
--- a/app/helpers/application_settings_helper.rb
+++ b/app/helpers/application_settings_helper.rb
@@ -258,6 +258,8 @@ def visible_attributes
       :authorized_keys_enabled,
       :auto_devops_enabled,
       :auto_devops_domain,
+      :autocomplete_users_limit,
+      :autocomplete_users_unauthenticated_limit,
       :concurrent_github_import_jobs_limit,
       :concurrent_bitbucket_import_jobs_limit,
       :concurrent_bitbucket_server_import_jobs_limit,
diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb
index 17adf898ff36630d82e878aadb7bc65c995e941e..c5f9efb577526e20302b6230dbcebec085948fa9 100644
--- a/app/models/application_setting.rb
+++ b/app/models/application_setting.rb
@@ -573,6 +573,8 @@ def self.kroki_formats_attributes
 
   with_options(numericality: { only_integer: true, greater_than: 0 }) do
     validates :ai_action_api_rate_limit,
+      :autocomplete_users_limit,
+      :autocomplete_users_unauthenticated_limit,
       :bulk_import_concurrent_pipeline_batch_limit,
       :code_suggestions_api_rate_limit,
       :concurrent_bitbucket_import_jobs_limit,
@@ -679,6 +681,8 @@ def self.kroki_formats_attributes
   validates :resource_usage_limits, json_schema: { filename: 'resource_usage_limits' }
 
   jsonb_accessor :rate_limits,
+    autocomplete_users_limit: [:integer, { default: 300 }],
+    autocomplete_users_unauthenticated_limit: [:integer, { default: 100 }],
     concurrent_bitbucket_import_jobs_limit: [:integer, { default: 100 }],
     concurrent_bitbucket_server_import_jobs_limit: [:integer, { default: 100 }],
     concurrent_github_import_jobs_limit: [:integer, { default: 1000 }],
diff --git a/app/models/application_setting_implementation.rb b/app/models/application_setting_implementation.rb
index de0f6de43af87130010cfa3f49e8034fabfc232f..ccf2afa7945e15d36f49006bdd16d923cffc6bcd 100644
--- a/app/models/application_setting_implementation.rb
+++ b/app/models/application_setting_implementation.rb
@@ -44,6 +44,8 @@ def defaults # rubocop:disable Metrics/AbcSize
         allow_possible_spam: false,
         asset_proxy_enabled: false,
         authorized_keys_enabled: true, # TODO default to false if the instance is configured to use AuthorizedKeysCommand
+        autocomplete_users_limit: 300,
+        autocomplete_users_unauthenticated_limit: 100,
         ci_max_total_yaml_size_bytes: 314572800, # max_yaml_size_bytes * ci_max_includes = 2.megabyte * 150
         commit_email_hostname: default_commit_email_hostname,
         container_expiration_policies_enable_historic_entries: false,
diff --git a/app/validators/json_schemas/application_setting_rate_limits.json b/app/validators/json_schemas/application_setting_rate_limits.json
index 4325aeeed5ff4470fe8c818aee6589f073efffb0..f53ab1c23e9d443b721fb76378acf8a34b14fb58 100644
--- a/app/validators/json_schemas/application_setting_rate_limits.json
+++ b/app/validators/json_schemas/application_setting_rate_limits.json
@@ -4,6 +4,16 @@
   "type": "object",
   "additionalProperties": false,
   "properties": {
+    "autocomplete_users_limit": {
+      "type": "integer",
+      "minimum": 0,
+      "description": "Number of authenticated requests allowed to the GET /autocomplete/users endpoint."
+    },
+    "autocomplete_users_unauthenticated_limit": {
+      "type": "integer",
+      "minimum": 0,
+      "description": "Number of unauthenticated requests allowed to the GET /autocomplete/users endpoint."
+    },
     "concurrent_bitbucket_import_jobs_limit": {
       "type": "integer",
       "minimum": 1,
diff --git a/config/feature_flags/gitlab_com_derisk/autocomplete_users_rate_limit.yml b/config/feature_flags/gitlab_com_derisk/autocomplete_users_rate_limit.yml
new file mode 100644
index 0000000000000000000000000000000000000000..a9103b9b110f3c330a5552342973e0a4ad4e403d
--- /dev/null
+++ b/config/feature_flags/gitlab_com_derisk/autocomplete_users_rate_limit.yml
@@ -0,0 +1,9 @@
+---
+name: autocomplete_users_rate_limit
+feature_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/368926
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/183244
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/523595
+milestone: '17.10'
+group: group::authentication
+type: gitlab_com_derisk
+default_enabled: false
diff --git a/lib/api/settings.rb b/lib/api/settings.rb
index a5254b999c02155a790ca6cd4411cc8f72de1154..2b746d3c549b90dc0bafd0a5f632c4c0264de80d 100644
--- a/lib/api/settings.rb
+++ b/lib/api/settings.rb
@@ -219,6 +219,8 @@ def filter_attributes_using_license(attrs)
       optional :concurrent_relation_batch_export_limit, type: Integer, desc: 'Maximum number of simultaneous batch export jobs to process.'
       optional :bulk_import_enabled, type: Boolean, desc: 'Enable migrating GitLab groups and projects by direct transfer'
       optional :bulk_import_max_download_file, type: Integer, desc: 'Maximum download file size in MB when importing from source GitLab instances by direct transfer'
+      optional :autocomplete_users_limit, type: Integer, desc: 'Rate limit for authenticated requests to users autocomplete endpoint'
+      optional :autocomplete_users_unauthenticated_limit, type: Integer, desc: 'Rate limit for authenticated requests to users autocomplete endpoint'
       optional :concurrent_github_import_jobs_limit, type: Integer, desc: 'Github Importer maximum number of simultaneous import jobs'
       optional :concurrent_bitbucket_import_jobs_limit, type: Integer, desc: 'Bitbucket Cloud Importer maximum number of simultaneous import jobs'
       optional :concurrent_bitbucket_server_import_jobs_limit, type: Integer, desc: 'Bitbucket Server Importer maximum number of simultaneous import jobs'
diff --git a/lib/gitlab/application_rate_limiter.rb b/lib/gitlab/application_rate_limiter.rb
index 24521414d8e86a9afaa3d56ac6a164f54ce524c1..a849f477097248777be4a826bcdf3bf28dd68d9d 100644
--- a/lib/gitlab/application_rate_limiter.rb
+++ b/lib/gitlab/application_rate_limiter.rb
@@ -19,6 +19,8 @@ class << self
       # and only do that when it's needed.
       def rate_limits # rubocop:disable Metrics/AbcSize
         {
+          autocomplete_users: { threshold: -> { application_settings.autocomplete_users_limit }, interval: 1.minute },
+          autocomplete_users_unauthenticated: { threshold: -> { application_settings.autocomplete_users_unauthenticated_limit }, interval: 1.minute },
           issues_create: { threshold: -> { application_settings.issues_create_limit }, interval: 1.minute },
           notes_create: { threshold: -> { application_settings.notes_create_limit }, interval: 1.minute },
           project_export: { threshold: -> { application_settings.project_export_limit }, interval: 1.minute },
diff --git a/spec/controllers/autocomplete_controller_spec.rb b/spec/controllers/autocomplete_controller_spec.rb
index 257cb6adc007568ad13090a3bb86d2c57f4eebbb..54d4b1c3ad7017bc8a7a6a757609c132ae557451 100644
--- a/spec/controllers/autocomplete_controller_spec.rb
+++ b/spec/controllers/autocomplete_controller_spec.rb
@@ -238,7 +238,25 @@
       end
     end
 
-    it_behaves_like 'rate limited endpoint', rate_limit_key: :search_rate_limit do
+    context 'when autocomplete users feature flag is disabled' do
+      before do
+        stub_feature_flags(autocomplete_users_rate_limit: false)
+      end
+
+      it_behaves_like 'rate limited endpoint', rate_limit_key: :search_rate_limit do
+        let(:current_user) { user }
+
+        def request
+          get(:users, params: { search: 'foo@bar.com' })
+        end
+
+        before do
+          sign_in(current_user)
+        end
+      end
+    end
+
+    it_behaves_like 'rate limited endpoint', rate_limit_key: :autocomplete_users do
       let(:current_user) { user }
 
       def request
diff --git a/spec/models/application_setting_spec.rb b/spec/models/application_setting_spec.rb
index be7d08e9273e484e451ce89a0d7b6a1e8bccacd9..4d90c8de03979d82df34951bf5820e1aed8971dc 100644
--- a/spec/models/application_setting_spec.rb
+++ b/spec/models/application_setting_spec.rb
@@ -38,6 +38,8 @@
     it { expect(setting.concurrent_bitbucket_server_import_jobs_limit).to eq(100) }
     it { expect(setting.nuget_skip_metadata_url_validation).to be(false) }
     it { expect(setting.silent_admin_exports_enabled).to be(false) }
+    it { expect(setting.autocomplete_users_limit).to eq(300) }
+    it { expect(setting.autocomplete_users_unauthenticated_limit).to eq(100) }
     it { expect(setting.group_api_limit).to eq(400) }
     it { expect(setting.group_invited_groups_api_limit).to eq(60) }
     it { expect(setting.group_projects_api_limit).to eq(600) }
@@ -337,6 +339,8 @@ def many_usernames(num = 100)
       where(:attribute) do
         %i[
           helm_max_packages_count
+          autocomplete_users_limit
+          autocomplete_users_unauthenticated_limit
           bulk_import_concurrent_pipeline_batch_limit
           code_suggestions_api_rate_limit
           concurrent_bitbucket_import_jobs_limit
diff --git a/spec/requests/api/settings_spec.rb b/spec/requests/api/settings_spec.rb
index c5d9e729032b46bd978db931aa2bf1d78b0c2fb4..7d2559603d0836ccfdf0433806d760f6e5cc4238 100644
--- a/spec/requests/api/settings_spec.rb
+++ b/spec/requests/api/settings_spec.rb
@@ -1161,6 +1161,22 @@
       end
     end
 
+    context 'with rate limit settings' do
+      context 'with users autocomplete rate limits' do
+        it 'updates the settings' do
+          put(
+            api("/application/settings", admin),
+            params: { autocomplete_users_limit: 4242,
+                      autocomplete_users_unauthenticated_limit: 42 }
+          )
+
+          expect(response).to have_gitlab_http_status(:ok)
+          expect(json_response['autocomplete_users_limit']).to eq(4242)
+          expect(json_response['autocomplete_users_unauthenticated_limit']).to eq(42)
+        end
+      end
+    end
+
     context 'security txt settings' do
       let(:content) { "Contact: foo@acme.com" }