惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
I
InfoQ
B
Blog RSS Feed
B
Blog
Microsoft Azure Blog
Microsoft Azure Blog
Vercel News
Vercel News
Recent Announcements
Recent Announcements
小众软件
小众软件
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
P
Palo Alto Networks Blog
S
Schneier on Security
宝玉的分享
宝玉的分享
The Hacker News
The Hacker News
Latest news
Latest news
T
Threat Research - Cisco Blogs
Last Week in AI
Last Week in AI
H
Hackread – Cybersecurity News, Data Breaches, AI and More
云风的 BLOG
云风的 BLOG
T
The Exploit Database - CXSecurity.com
T
Tor Project blog
A
Arctic Wolf
博客园 - 叶小钗
K
Kaspersky official blog
U
Unit 42
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
M
MIT News - Artificial intelligence
V
Vulnerabilities – Threatpost
H
Help Net Security
V2EX - 技术
V2EX - 技术
Security Archives - TechRepublic
Security Archives - TechRepublic
The Last Watchdog
The Last Watchdog
C
CXSECURITY Database RSS Feed - CXSecurity.com
Cisco Talos Blog
Cisco Talos Blog
N
News and Events Feed by Topic
Cloudbric
Cloudbric
Hacker News: Ask HN
Hacker News: Ask HN
博客园 - 三生石上(FineUI控件)
C
Cisco Blogs
D
DataBreaches.Net
Project Zero
Project Zero
The Cloudflare Blog
罗磊的独立博客
WordPress大学
WordPress大学
Y
Y Combinator Blog
Attack and Defense Labs
Attack and Defense Labs
腾讯CDC
V
V2EX
F
Full Disclosure
H
Heimdal Security Blog

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant Common SOC 2 Failures (Real World) Stop Vibe-Checking Your AI App: A Practical Guide to Evals How to Use SonarQube and SonarScanner Locally to Level Up Your Code Quality Your Next To-Do App Is Dead — I Replaced Mine with an OpenClaw AI Sign a Nostr event in 60 lines of Python using coincurve — no nostr-sdk, no nbxplorer, no rust toolchain ITGC Audit Explained Like You’re in Big 4 Patch Tuesday abril 2026: Microsoft parcha 163 vulnerabilidades y un zero-day en SharePoint Stop scraping everything: a better way to track competitor price changes Listing on MCPize + the Official MCP Registry while routing payments OUTSIDE the marketplace — how I kept 100% of my x402 revenue Building an AI-Powered Risk Intelligence System Using Serverless Architecture Why We Ripped Function Overloading Out of Our AI Toolchain Testing AI-Generated Code: How to Actually Know If It Works SaaS Churn Is Killing Your Business. Here Is What to Do About It (Without a Support Team) The Speed of AI Is No Longer Linear - And Self-Improving Models Are Why How to Implement RBAC for MCP Tools: A Practical Guide for Engineering Teams From Standard Quote to Persuasive Proposal: AI Automation for Arborists I built a CLI that scaffolds complete multi-tenant SaaS apps Axios CVE-2025–62718: The Silent SSRF Bug That Could Be Hiding in Your Node.js App Right Now The dashboard that ended our friendship Data Pipelines Explained Simply (and How to Build Them with Python) The Hidden Cost of AI Systems Nobody Talks About. undefined vs undeclared, and how typeof behaves Switching from file-based jobs to NATS/Kafka in Rust without changing code io_uring Adventures: Rust Servers That Love Syscalls Why Agentic AI is Killing the Traditional Database The POUR principles of web accessibility for developers and designers Quantum Neural Network 3D — A Deep Dive into Interactive WebGL Visualization How To Install Caveman In Codex On macOS And Windows Automation Pipeline Reliability: Why Your Workflow Breaks When Nobody Is Watching I Built an 'Open World' AI Coding Agent — It Works From ANY Folder From Freelancing to Product: A Tech Service Company's SaaS Transformation China's AI Giants: Adding Tencent Hunyuan & ByteDance Doubao to AI University (74 Providers) On the Vibe Coders and Their Lies clerk: Auto-Summarize Your Claude Code Sessions AI Weekly — 2026/04/10–04/17 | The Model Lockdown Is Here, but the Toolchain Is the Real Battleground AI 週報 — 2026/04/10–2026/04/17 模型封鎖潮來了,但工具鏈才是真戰場 Maybe this is how Open-Source apps are born... 🚀 Fine-Tune LLMs with LoRA and QLoRA: 2026 Guide tRPC v11 + Next.js App Router: End-to-End Type Safety Without the Boilerplate ShadCN UI in 2026: Why I Stopped Installing Component Libraries and Started Owning My Components SaaS Billing in React Server Components: Stripe + Supabase Without a Single `useEffect` Join our DEV Weekend Challenge — $1,000 in Prizes Across TEN winners! Submissions Due April 20 at 6:59 AM UTC. Implementing FSRS Spaced Repetition in Flutter + Supabase — Adding Memory Science to an AI Learning App "I Texted My Localhost From the Train — Claude Code Fixed the Bug Before I Got Home" I Built a Sales Prep AI and It Went Deeper Than Expected Design to Code #2: One JSON, Eleven Outputs Solving the 100M-Row Problem: A Summary Table Pattern for High-Volume Push Notification Logs Flutter Web With Wasm: What Actually Changes For Developers I Built 50 Royalty-Free Soundtracks for My Side Project in a Weekend Using AI Music Generation The Vibe Coding Security Checklist: 7 Things to Check Before You Ship Stop Letting Googlebot Guess Fix Your React App's SEO Right Desconstruindo o Streaming do LinkedIn: Como Criar um Engine de Extração de Vídeo de Alta Performance com HLS e FFmpeg (EDA Part-1) EDA (Exploratory Data Analysis) Explained With Real Life — Why Looking at Your Data Is the Most Important Step in Machine Learning Brand Relationship Management at Scale: Our 4-Touch Outreach System for 200+ Brands Why String.fromEnvironment() Might Return an Empty String in Dart JGuardrails 1.0.0 — Hardening Java LLM Apps Against Jailbreaks, Toxicity, and Prompt Injection Plan and Schedule a Full Week of Threads Content From One Claude Conversation Coding Cat Oran Ep3, Five Tables Changed Everything Updated: BFF Pattern I'm done watching freelancers get buried by 200 proposals. So I'm building the alternative. This is my first post BFS Algorithm in Java Step by Step Tutorial with Examples Tracking LLM Pricing Monthly: An Open Dataset for 22 AI Models How We Measure Content ROI on a Comparison Site: Revenue Attribution Without Perfect Data Introducing Nova AI Ops: The AI-Native Operating System for SRE Teams I built a free desktop video downloader for Windows — Grabbit How Talkie OCR Helps Vision-Impaired & Dyslexic Users Read the World Around Them VRCFaceTracking安装和iPhone面捕配置教程,有bug Even CrowdStrike Can't See Your Agents The Automation Gold Rush: What n8n Workflows and Claude Are Opening Up for Developers Right Now
Reciprocal Rank Fusion on free Elasticsearch: licensing, workarounds, and the OpenSearch alternative
Maciej Łopalewski · 2026-06-24 · via DEV Community

Reciprocal Rank Fusion (RRF) on Elasticsearch is gated to the Enterprise tier. On the Basic/free tier, querying with the rrf retriever returns a 403:

{
  "error": {
    "root_cause": [
      {
        "type": "security_exception",
        "reason": "current license is non-compliant for [Reciprocal Rank Fusion (RRF)]",
        "license.expired.feature": "Reciprocal Rank Fusion (RRF)"
      }
    ],
    "type": "security_exception",
    "reason": "current license is non-compliant for [Reciprocal Rank Fusion (RRF)]",
    "license.expired.feature": "Reciprocal Rank Fusion (RRF)"
  },
  "status": 403
}

This has held since RRF first appeared as a technical preview in 8.8 (May 2023), through the 8.16 GA release (November 2024), and into the 9.x line. The linear retriever added in 8.18 / 9.0 is gated the same way, also at Enterprise. Three practical workarounds exist: implement RRF yourself in application code, combine BM25 and vector results with a normalized linear combination, or move to OpenSearch - which ships RRF, score normalization (including z-score), and late-interaction reranking by a field under Apache 2.0 license.

What RRF actually does

Reciprocal Rank Fusion combines multiple ranked result sets into a single ranking based on document positions rather than raw scores. The formula is:

score(d) = Σ 1 / (k + rank_i(d))

where rank_i(d) is the document's position in the i-th result list and k is a smoothing constant. The original paper from Cormack, Clarke, and Büttcher (SIGIR 2009) used k=60 and noted the choice was not critical. Their Table 1 shows MAP barely moves across k ∈ [10, 100] - only at the extremes (k=0 or k=500) does the score drop meaningfully. Elastic and OpenSearch both default the RRF rank constant to 60, following the original paper's convention.

The reason RRF matters for hybrid search: BM25 scores are unbounded and query/corpus-dependent, while vector similarity scores live on a different scale and distribution depending on the similarity function and embedding model. Naively summing them lets one method dominate purely from scale. RRF discards the scores entirely and works only with ranks, which sidesteps the normalization problem with no tuning required.

What Basic actually gets you, and what it doesn't

The Elastic subscriptions matrix splits hybrid-search-related features across three paid tiers. Knowing what's behind each wall is more useful than the headline "RRF is paid":

Feature Basic / free Platinum Enterprise
Vector search (kNN)
Standard, kNN, pinned, rescorer retrievers
Similarity functions for vector fields
Synonym management
ELSER (learned sparse encoder)
Elastic Rerank
Inference API
RRF for hybrid search
Linear, rule, text similarity re-ranker retrievers
Rank Vectors (for MaxSim)
DiskBBQ
Indexing vectors with GPUs
Query Rules
Learning to Rank

Source: https://www.elastic.co/subscriptions

The pattern is clear. Basic gives you the building blocks for client-side hybrid search - kNN runs, BM25 runs, both can be queried separately. Platinum unlocks Elastic-managed inference and ELSER. Enterprise is where the actual modern hybrid search features live: rank fusion, learned sparse rerankers, late interaction, GPU vector indexing, learning to rank.

If you're on Basic and you want hybrid search, you're either reimplementing pieces of Enterprise in application code, switching engines, or starting a trial.

The licensing timeline

The gating has been continuous and has expanded, not relaxed. The August 2024 license change that re-added AGPLv3 to Elasticsearch made the source code open source again but did not change which features the default ELv2 distribution gates behind paid tiers.

Version Date What changed
8.4 August 2022 First hybrid search support
8.8 May 2023 RRF added as technical preview, gated
8.14 June 2024 Retrievers framework introduced
Pre-8.16 August 2024 Elastic announced AGPLv3 as an additional source-code license option; feature-tier gating in the default distribution unchanged
8.16 November 2024 RRF and retrievers reach GA, gated to Enterprise
8.18 / 9.0 April 2025 Linear retriever added, also gated to Enterprise
9.0.1 Basic June 2025 Linear retriever still throws license error in production
Late 2025 September 2025 Per-retriever weights added to RRF retriever (still Enterprise-gated)

Self-managed deployments can start a 30-day trial that gives access to all subscription features, including Enterprise-tier features, for evaluation. Elastic Cloud trials are 14 days. Elastic also publishes a trial extension form that grants one additional 30-day extension on request.

Workaround 1: Implement RRF in your application

Run BM25 and kNN as two separate queries against Elasticsearch Basic, then fuse the result lists in application code. The fusion logic is roughly seven lines of Python:

from collections import defaultdict

def rrf_fusion(rankings: list[list[str]], k: int = 60) -> list[tuple[str, float]]:
    """Combine multiple ranked lists of document IDs using Reciprocal Rank Fusion."""
    scores: dict[str, float] = defaultdict(float)
    for ranking in rankings:
        for rank, doc_id in enumerate(ranking, start=1):
            scores[doc_id] += 1.0 / (k + rank)
    return sorted(scores.items(), key=lambda x: x[1], reverse=True)

Calling it with a BM25 result list and a kNN result list returns the fused ranking:

bm25_ids = [hit["_id"] for hit in es.search(index=idx, query=match_query)["hits"]["hits"]]
knn_ids = [hit["_id"] for hit in es.search(index=idx, knn=knn_query)["hits"]["hits"]]

fused = rrf_fusion([bm25_ids, knn_ids])
top_10_ids = [doc_id for doc_id, _ in fused[:10]]

The trade-offs are clear. You pay two round trips instead of one, you lose retrievers-specific features like inner_hits and the unified pagination model, and you have to rehydrate the document _source after fusion - typically with an mget call against the top IDs. In return, you get RRF ranking on the Basic tier with no licensing exposure. In many RAG-style systems embedding generation and kNN latency dominate, but the actual breakdown depends on cache state, candidate window size, and deployment topology - measure for your workload before assuming the extra round trip is free.

Workaround 2: Linear combination with manual normalization

The Basic tier still allows two separate queries fused with a weighted sum, as long as the math happens in your application rather than through the gated linear retriever. Min-max normalize both score sets per query - using the min and max from each result list as the range - then combine with a weight α:

from collections import defaultdict

def minmax_normalize(score: float, lo: float, hi: float) -> float:
    rng = hi - lo
    return 1.0 if rng == 0 else (score - lo) / rng

def linear_fusion(bm25_hits: list[dict], knn_hits: list[dict], alpha: float = 0.5):
    scores: dict[str, float] = defaultdict(float)

    if bm25_hits:
        s = [h["_score"] for h in bm25_hits]
        lo, hi = min(s), max(s)
        for h in bm25_hits:
            scores[h["_id"]] += alpha * minmax_normalize(h["_score"], lo, hi)

    if knn_hits:
        s = [h["_score"] for h in knn_hits]
        lo, hi = min(s), max(s)
        for h in knn_hits:
            scores[h["_id"]] += (1 - alpha) * minmax_normalize(h["_score"], lo, hi)

    return sorted(scores.items(), key=lambda x: x[1], reverse=True)

When you have labeled query data, calibrated linear can beat RRF. Elastic's research on ELSER + BM25 across BEIR reports that around 40 annotated queries are enough for linear combination to start outperforming RRF, and with 300 calibration queries the optimized linear combination achieved a 6% NDCG@10 improvement over ELSER alone - compared to RRF's 1.4% improvement over the same baseline. Without calibration data, RRF is the safer default - it requires no tuning and is far less sensitive to score distribution mismatches.

Workaround 3: Switch to OpenSearch

OpenSearch ships hybrid search and RRF under Apache 2.0 with no feature-tier licensing. The native hybrid query and normalization-processor (min_max, L2) landed in 2.10 (September 25, 2023). Native RRF landed in 2.19 (February 11, 2025). The 3.x line has continued to invest heavily in vector and hybrid search since then.

Version Date Hybrid search additions
2.10 September 25, 2023 First hybrid query, normalization-processor (min_max, L2)
2.19 February 11, 2025 Native RRF (score-ranker-processor), pagination support, hybrid_score_explanation
3.0 May 6, 2025 z-score normalization, lower bound for min-max, inner hits in hybrid, GPU acceleration for vector index builds (experimental)
3.1 June 24, 2025 GPU acceleration for vector index builds GA, hybrid query performance improvements (up to 65% latency reduction)
3.3 October 14, 2025 Up to 20% faster hybrid for lexical subqueries, lateInteractionScore for reranking by a field using externally hosted ColBERT/ColPali models

The trend continued after 3.3: OpenSearch 3.4, released in December 2025, added further vector-search investment such as k-NN memory-optimized search warmup, native FP16 vector scoring, and JDK 25 support. OpenSearch 3.5 followed in February 2026, and 3.6.0 - the project's first long-term support release - was published April 7, 2026. Refer to the OpenSearch version history and downloads page for the current state.

The score-ranker-processor documentation also shows that custom subquery weights are supported via the parameters.weights array on RRF - useful when you want to weight the BM25 and vector legs differently rather than treat them equally. Elasticsearch added per-retriever weights to its RRF retriever in late 2025 as well, but because the RRF retriever itself is Enterprise-gated, this doesn't change the Basic-tier workaround story.

The mapping to Elasticsearch's paid tiers is striking. Several broadly comparable capabilities that are Enterprise-only in Elasticsearch's built-in implementation are open-source in OpenSearch:

Capability Elasticsearch tier OpenSearch tier
RRF rank fusion Enterprise Apache 2.0 (since 2.19)
Built-in weighted score fusion Enterprise (linear retriever) Apache 2.0 score-based hybrid normalization/combination via search pipelines (since 2.10)
Multiple normalization methods (min-max, L2, z-score) Enterprise Apache 2.0 (z-score in 3.0)
Late-interaction reranking by a field (ColBERT/ColPali workflows) Enterprise (Rank Vectors) Apache 2.0 (lateInteractionScore in 3.3)
GPU acceleration for vector index builds Enterprise Apache 2.0 (3.0 experimental, 3.1 GA)
Learning to Rank Enterprise Apache 2.0 (LTR plugin)

If the project is greenfield and does not depend on Elastic-specific features such as ELSER, Elastic Rerank, ES|QL, or the managed Inference API integrations, OpenSearch is the cleanest path. The migration cost from an existing Elasticsearch deployment is non-trivial - index format compatibility, client library differences, and Kibana versus OpenSearch Dashboards differences all add up - but the functional gap between the free tiers has generally widened for hybrid and vector-search use cases.

When paying for Enterprise makes sense

The trial-then-pay path is reasonable when the team needs text_similarity_reranker for semantic reranking with hosted models, the calibrated linear retriever, MaxSim with rank vectors for ColBERT-style retrieval, GPU vector indexing for billion-scale corpora, learning-to-rank pipelines, or production support contracts. None of this comes for free, and reimplementing it is more expensive than the license for organizations with substantial search infrastructure. For teams whose only blocker is RRF specifically, the workarounds above usually win on cost and are straightforward to implement for simple two-leg hybrid retrieval.

What most teams actually need

Most teams that hit the RRF license error don't actually need RRF specifically - they need hybrid search to work. Manual linear combination with normalized scores is often sufficient for a first production hybrid-search implementation on any Elasticsearch version. The core RRF scoring loop is another twenty lines of code on top of that - production deployments will additionally want pagination, deduplication, an mget rehydration step, tie-breaking, and observability around the fused ranking. And for projects starting fresh in 2026, the open-source answer keeps getting better with every OpenSearch release.

Originally published at https://u11d.com on June 3, 2026.