Optimize Zoekt search response payload
The Zoekt coordinating node returns the full Zoekt response format to Rails, which parses the entire JSON body in one shot. An [S3 incident (INC-7931)](https://gitlab.com/gitlab-com/gl-infra/production/-/work_items/21421) occurred when `Gitlab::Json.safe_parse` was introduced — its 100k JSON element limit was exceeded by normal group-level search results. **Root cause:** Both standard and multi-match search send `max_file_match_results = 5,000` (or UNLIMITED for standard). Combined with the 5,000 line match window, the coordinating node can return thousands of file objects in a single response. Each file + line match contributes ~52 JSON elements (not ~20 as originally estimated), so the 100k limit is hit at ~1,900 files with 1 match each, or ~580 files with 5 matches each. Rails only needs ~200 results (10 pages × 20 per page) for the common case. **Related:** https://gitlab.com/gitlab-com/gl-infra/production-engineering/-/work_items/28457 ## Issues ### Short-term — reduce payload size 1. #591911 — Use `TotalLineMatchCount` / `TotalFileMatchCount` for accurate result counts (must land first) 2. #591910 — Cap `max_file_match_results` to `max(Cache::MAX_PAGES, current_page) * per_page` (200 for pages 1-10, scales for deeper pages) ### Medium-term — re-enable safe_parse 3. #591912 — Re-enable `Gitlab::Json.safe_parse` behind a derisk feature flag (blocked by #591910 and #591911) ### Medium-term — offset pagination (independent track) 4. #591915 — Support offset-based pagination in the coordinating node (standard search) 5. #591917 — Support offset-based pagination for multi-match search mode (blocked by #591915) ### Long-term — wire format optimization 6. #591913 — Redesign coordinating node response format for efficiency ## Dependency chain ``` #591911 (fix counts) ──blocks──► #591910 (cap results) ──blocks──► #591912 (safe_parse) #591911 (fix counts) ──blocks──► #591912 (safe_parse) #591915 (offset: standard) ──blocks──► #591917 (offset: multi-match) ``` - #591911 and #591910 are the critical path for re-enabling `safe_parse` - #591915/#591917 (offset pagination) are an independent optimization track — no blocking dependency on #591910 - All risky changes are rolled out behind feature flags ## Element count formula ``` total_elements = 24 + 22*N + 30*N*M ``` - N = files, M = line matches per file (assuming 1 fragment, 1 branch) - 24 = fixed overhead (envelope + result object) - 22 per file = 10 kv-pairs + array appends - 30 per line match = 10 kv-pairs + 1 fragment (4 kv-pairs) + array appends
epic