docs(search): hybrid-retrieval reshape plan (search won't scale as-is — proven)#922
Open
seonghobae wants to merge 1 commit into
Open
docs(search): hybrid-retrieval reshape plan (search won't scale as-is — proven)#922seonghobae wants to merge 1 commit into
seonghobae wants to merge 1 commit into
Conversation
/api/search seq-scans every query and cannot use FTS/vector indexes because of query shape (no @@ predicate; FTS+vector fused into one ORDER BY), not just missing indexes. Verified with pgvector 0.8.2 EXPLAIN: the current shape seq-scans even WITH GIN+HNSW present; a @@-gated query uses the GIN index and a pure ANN ORDER BY uses HNSW. Documents the correct hybrid-retrieval reshape (lexical arm + vector arm + RRF fuse) plus the accompanying migration, to be landed test-first through RED/GREEN. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017RkKdtHRLG4wSLh6PVsp8J
Contributor
OpenCode Review Overview
Changed-File Evidence Mapflowchart LR
PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
Evidence --> S1["Docs: 2026-07-05-search-scalability-hybrid-retrieval.md"]
S1 --> I1["operator or user guidance"]
I1 --> R1["Review risk: Docs: 2026-07-05-search-scalability-hybrid-retrieval.md"]
R1 --> V1["docs review"]
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
/api/searchdoes a full sequential scan on every query and cannot use any index — the single largest scaling cliff in the product. The root cause is query shape, not just missing indexes:_search_score(backend/api/search.py) has no@@text-match predicate and fuses FTS + vector into oneORDER BY, which independently defeats both GIN and ANN indexing.Evidence (pgvector 0.8.2,
EXPLAIN (COSTS OFF), spun up a throwaway PG to verify)ts_rank_cd - cosine_distanceORDER BY, no@@)WHERE ... @@ plainto_tsqueryORDER BY embedding <=> q LIMITSo a naive "add indexes" migration would create indexes the planner never uses. The reshape and the indexes must land together.
What this PR is
A docs-only plan (matches
docs/plans/convention) for the correct fix: a two-arm hybrid retrieval (lexical arm gated by@@+GIN, vector arm via pure ANN+HNSW, fused with RRF/normalized score) plus the accompanying dialect-guarded, pgvector-version-aware,CONCURRENTLYindex migration0010. Because it changes ranking and result membership on a core path, it should land test-first (Postgres-backedEXPLAINassertions), not autonomously.Why now
This is a P0 trust-at-scale blocker: an enterprise mailbox import turns search into a full-table scan per keystroke. The plan de-risks it and corrects the intuitive-but-wrong "just add indexes" approach with proof.
🤖 Generated with Claude Code