Limit projects and warn when traversal ID indexing incomplete for Zoekt exact code search

Summary

Limits the number of projects searched and displays a warning when group-level Zoekt searches include too many projects while traversal ID indexing is still in progress.

image

How to validate locally

Apply this diff and run a search. Something like http://localhost:3000/search?scope=blobs&search=hello&group_id=24

diff --git a/ee/app/models/search/zoekt/features/traversal_id_search.rb b/ee/app/models/search/zoekt/features/traversal_id_search.rb
index cd907aa7a6abc7..8440a03a2c3cda 100644
--- a/ee/app/models/search/zoekt/features/traversal_id_search.rb
+++ b/ee/app/models/search/zoekt/features/traversal_id_search.rb
@@ -4,7 +4,7 @@ module Search
   module Zoekt
     module Features
       class TraversalIdSearch < BaseFeature
-        self.minimum_schema_version = 2531
+        self.minimum_schema_version = 9999
       end
     end
   end
diff --git a/ee/app/models/search/zoekt/settings.rb b/ee/app/models/search/zoekt/settings.rb
index c1033c0e35613d..bc561c6c22c63c 100644
--- a/ee/app/models/search/zoekt/settings.rb
+++ b/ee/app/models/search/zoekt/settings.rb
@@ -23,7 +23,7 @@ module Settings
       DEFAULT_NUM_REPLICAS = 1
       DEFAULT_TRIGRAM_MAX = 20_000
       DEFAULT_FORCE_REINDEXING_PERCENTAGE = 0.25
-      DEFAULT_MAX_PROJECTS_LEGACY_SEARCH = 1_000
+      DEFAULT_MAX_PROJECTS_LEGACY_SEARCH = 2
       DISABLED_VALUE = '0'
       DURATION_BASE_REGEX = %r{([1-9]\d*)([mhd])}
       DURATION_INTERVAL_REGEX = %r{\A(?:0|#{DURATION_BASE_REGEX})\z}

Changes

This MR implements two safety mechanisms to prevent performance degradation during Zoekt exact code searches when traversal_id_search is not yet available:

1. Project Limiting in AccessBranchBuilder

  • Limits group-level searches to first 1,000 projects (configurable via zoekt_max_projects_legacy_search setting)
  • Only applies when:
    • Searching at group level (not project-specific)
    • traversal_id_search feature flag is not available
  • Skips group-based traversal ID filters when limiting is active
  • Prevents building overly complex boolean filters with individual project IDs

2. User Warning in SearchService

  • Displays warning message when search scope exceeds project limit
  • Message: "Your search includes too many projects while traversal ID indexing is still in progress. Only the first 1,000 projects are shown. Please contact your administrator."
  • Logs warning with user/group context for monitoring
  • Only shown during group-level searches without traversal_id_search

3. Configurable Setting

  • New zoekt_max_projects_legacy_search application setting (default: 1,000)
  • Allows administrators to adjust the project limit threshold
  • Exposed in admin settings UI

4. Comprehensive Test Coverage

  • Validates project limiting behavior in AccessBranchBuilder
  • Tests warning message generation in SearchService
  • Verifies bypasses when traversal_id_search is available
  • Confirms project-level searches are unaffected

Why this change

Without traversal_id_search, Zoekt authorization must enumerate individual project IDs to build search filters. When searching across 1,000+ projects, this creates large boolean filter expressions that can significantly degrade search performance.

This change:

  • Protects search performance by limiting the scope to a manageable number of projects
  • Informs users that results may be incomplete and why
  • Provides clear path forward (enabling traversal ID indexing)
  • Is temporary - automatically disabled once traversal_id_search becomes available

Part of improving Zoekt search performance and reliability during feature rollout.

Edited by John Mason

Merge request reports

Loading