Retrieval & Search

Re-ranking Guide

Cross-encoder rerankers that re-score retrieved documents for precision - the highest-ROI improvement in most RAG retrieval pipelines.

45 min readIntermediateLast reviewed: 20 July 2026

Quick Summary

Re-ranking uses cross-encoders to rescore a shortlist of retrieved documents for precision before LLM generation.

One Analogy

Initial retrieval is casting a wide net; reranking picks the best fish from the catch before serving dinner.

Engineering Rule

Retrieve 20–50 with bi-encoders, rerank to 3–5 with a cross-encoder — never skip measuring precision@3 on your golden set.

Try the Reranking Lab

Retrieve broadly with Hybrid RAG, then refine candidate ordering with a cross-encoder before selecting the final context for generation.

Try Interactive Lab

TL;DR

  • Reranking re-scores retrieved documents using a cross-encoder that jointly evaluates query-document relevance - far more accurate than bi-encoder similarity alone.

  • Retrieve many (top-20 to top-50), rerank to few (top-3 to top-5) - reranking improves precision without sacrificing recall.

  • Cross-encoders are slow but accurate - they can't pre-compute document scores, so reranking runs at query time on a small candidate set.

  • One of the highest-ROI retrieval improvements for many RAG pipelines — reranking frequently improves precision with added latency that is often on the order of ~100–300ms in typical deployments (measure on your stack).

  • Example production models (current as of writing): Cohere Rerank and bge-reranker-v2-m3 — API for simplicity, self-hosted for data residency; re-evaluate as new releases ship.

Why This Matters

Initial retrieval (vector search, BM25, hybrid) optimizes for recall - getting the right document somewhere in the top-k results. But k=20 results often contain 15 irrelevant chunks. Passing all 20 to the LLM wastes context window, adds noise, increases cost, and degrades answer quality.

Reranking solves the precision problem. A cross-encoder reads the query and each candidate document together, producing a highly accurate relevance score. It reorders the initial results so the most relevant documents rank first.

Across many deployed RAG systems, adding a reranker is often one of the highest-impact quality improvements — more than switching embedding models, more than tuning chunk size, and more than prompt engineering. The latency cost is often ~100–300ms in typical deployments — acceptable for many applications, but benchmark on your SLA.

The Problem Re-ranking Solves

Bi-encoder embedding models (used in initial retrieval) encode queries and documents independently. The model never sees the query and document together, so it can't capture fine-grained interactions:

  • Does this document actually answer this specific question?
  • Is the relevant paragraph buried in a long chunk?
  • Does the document contradict the query's assumptions?

A query "How do I reset my password?" might retrieve a chunk about "password security best practices" (high embedding similarity) ahead of "password reset procedure" (lower similarity but actually answers the question).

Cross-encoder rerankers process [query, document] as a single input sequence. The transformer's attention mechanism captures precise query-document interactions that bi-encoders miss. This produces dramatically better relevance scores - at the cost of running inference on every query-document pair at query time.

How We Got Here

Reranking predates RAG. Learning-to-rank models reordered web search results for decades. Neural IR added cross-encoders that jointly encode query-document pairs, then deployed RAG pipelines adopted them as a common high-ROI precision stage after vector search and hybrid search.

Diagram: Evolution of reranking in retrieval

timeline
    title Reranking in IR
    2000s : Learning to rank (LambdaMART)
    2019 : MS MARCO cross-encoders
    2020 : Cohere Rerank API
    2022 : bge-reranker open source
    2023 : Rerank in vector DB query APIs
    2024 : Late interaction as LI-rerank stage

Cross-encoder rerankers became the default second stage in deployed RAG stacks once teams realized bi-encoder recall alone could not rank the right chunk first.

Stage Technique Role
First stage BM25 + dense ANN High recall (Hybrid Search)
Second stage Cross-encoder rerank High precision (this guide)
Alternative second stage Late interaction MaxSim Token-aware; different cost profile
Third stage (optional) LLM generation Synthesis with top-3 to top-5 chunks

Managed APIs (Cohere Rerank) and open models (bge-reranker-v2-m3) made reranking accessible without training custom rankers. Vector databases such as Qdrant and Weaviate now integrate rerankers in query pipelines.

What Is Re-ranking?

Re-ranking is a second-stage retrieval step that takes an initial set of candidate documents and reorders them by true relevance to the query. The reranker model (typically a cross-encoder) scores each query-document pair directly.

def rerank(query: str, documents: list[str], top_n: int = 5) -> list[tuple[str, float]]:
    pairs = [(query, doc) for doc in documents]
    scores = cross_encoder.predict(pairs)
    ranked = sorted(zip(documents, scores), key=lambda x: x[1], reverse=True)
    return ranked[:top_n]

The pipeline pattern:

Most deployed RAG systems separate offline indexing (load, chunk, embed, store) from online querying (embed query, retrieve, rerank, generate).

Initial retrieval casts a wide net (high recall). Reranking selects the best catches (high precision). When multi-query retrieval merges candidates from several transformed queries, deduplicate by chunk ID and rerank against the original user question — the union improves recall but increases noise without a rerank stage.

Diagram: Bi-encoder vs cross-encoder

flowchart LR
    subgraph bi [Bi-encoder retrieval]
        Q1[Query] --> EQ[Query embed]
        D1[Docs] --> ED[Doc embeds precomputed]
        EQ --> ANN[ANN similarity]
        ED --> ANN
    end
    subgraph ce [Cross-encoder rerank]
        Q2[Query + doc text] --> CE[Joint transformer]
        CE --> Score[Relevance score]
    end
    ANN --> Shortlist[Top 20-50]
    Shortlist --> CE

Bi-encoders precompute doc vectors; cross-encoders score pairs at query time on a shortlist only.

How Re-ranking Works

Bi-encoder vs Cross-encoder

Aspect Bi-encoder (Retrieval) Cross-encoder (Reranking)
Input Query and document encoded separately Query + document concatenated
Speed Fast - pre-compute document embeddings Slow - score each pair at query time
Accuracy Good (approximate similarity) Excellent (precise relevance)
Scale Millions of documents Tens to hundreds of candidates
Use case Initial retrieval Re-ranking top candidates

The retriever scores document chunks against the query embedding and returns the top-k passages that ground the generator.

Model Type Max Length Languages Deployment
Cohere rerank-v3.5 API 4096 tokens Multilingual API
bge-reranker-v2-m3 Cross-encoder 8192 tokens Multilingual Self-hosted
bge-reranker-v2-gemma Cross-encoder 4096 tokens Multilingual Self-hosted
Jina Reranker v2 API/self-hosted 8192 tokens Multilingual Both
ms-marco-MiniLM-L-6-v2 Cross-encoder 512 tokens English Self-hosted

Diagram: RAG query with reranking

sequenceDiagram
    participant U as User
    participant R as Retriever
    participant RR as Reranker
    participant L as LLM
    U->>R: question
    R->>R: hybrid top-25
    R->>RR: query + 25 chunks
    RR->>RR: cross-encoder scores
    RR->>L: top-5 chunks + question
    L-->>U: answer + citations

Reranking sits between retrieval and generation — typically 100–300ms for 25 document pairs.

Architecture

Reranking sits between retrieval and generation in the query pipeline:

Diagram: Production rerank architecture

flowchart TB
    Q[User query] --> H[Hybrid retriever]
    H --> F[Metadata filters]
    F --> C[Candidates k=25]
    C --> D[Deduplicate by doc]
    D --> RR[Cross-encoder rerank]
    RR --> T[Top-n to LLM]
    T --> G[Generate + cite]
    RR --> Log[Score logging]

Apply tenant and permission filters before reranking; log scores for failure diagnosis.

Key parameters:

  • Initial retrieval k: How many candidates to fetch (20–50)

  • Rerank top-n: How many to pass to the LLM (3–5)

  • Score threshold: Minimum reranker score to include (optional, model-dependent)

Step-by-Step Flow

Step 1: Configure initial retrieval for recall. Retrieve top-20 to top-50 using hybrid search. Cast a wide net - reranking handles precision.

Step 2: Choose a reranker model. Cohere Rerank for API simplicity. bge-reranker-v2-m3 for self-hosted multilingual.

Step 3: Score all candidates. Pass each query-document pair through the cross-encoder. Get a relevance score per document.

Step 4: Select top-n. Take the highest-scoring documents (typically 3–5). Optionally apply a minimum score threshold.

Step 5: Pass to LLM. Send reranked chunks as context. Include reranker scores in logs for debugging.

Step 6: Measure impact. Compare precision@k and answer quality with and without reranking on your eval set.

Real Production Example

A customer support RAG system retrieves 25 candidates, reranks to 5, and generates an answer:

import cohere
from dataclasses import dataclass

@dataclass
class RetrievedChunk:
    id: str
    text: str
    metadata: dict
    initial_score: float

class RerankerPipeline:
    def __init__(self, vector_store, cohere_client=None):
        self.store = vector_store
        self.cohere = cohere_client or cohere.Client()

    def retrieve(self, query: str, top_k: int = 25, filters: dict = None) -> list[RetrievedChunk]:
        results = self.store.hybrid_search(query, top_k=top_k, filters=filters)
        return [
            RetrievedChunk(id=r.id, text=r.text, metadata=r.metadata, initial_score=r.score)
            for r in results
        ]

    def rerank(self, query: str, chunks: list[RetrievedChunk], top_n: int = 5) -> list[RetrievedChunk]:
        if not chunks:
            return []

        response = self.cohere.rerank(
            model="rerank-v3.5",
            query=query,
            documents=[c.text for c in chunks],
            top_n=top_n,
        )

        reranked = []
        for result in response.results:
            chunk = chunks[result.index]
            chunk.initial_score = result.relevance_score
            reranked.append(chunk)

        return reranked

    def query(self, question: str, tenant_id: str) -> dict:
        candidates = self.retrieve(
            question, top_k=25, filters={"tenant_id": tenant_id}
        )
        reranked = self.rerank(question, candidates, top_n=5)

        context = "\n\n".join(
            f"[{i+1}] {c.text}" for i, c in enumerate(reranked)
        )
        answer = llm.generate(question, context)

        return {
            "answer": answer,
            "sources": [c.metadata for c in reranked],
            "reranker_scores": [c.initial_score for c in reranked],
        }

# Self-hosted alternative with sentence-transformers
from sentence_transformers import CrossEncoder

local_reranker = CrossEncoder("BAAI/bge-reranker-v2-m3")

def rerank_local(query: str, documents: list[str], top_n: int = 5):
    pairs = [[query, doc] for doc in documents]
    scores = local_reranker.predict(pairs)
    ranked = sorted(zip(documents, scores), key=lambda x: x[1], reverse=True)
    return ranked[:top_n]

The reranker pushes the specific "password reset procedure" document above generic "password security" content that the bi-encoder ranked higher.

Design Decisions

Decision Option A Option B When to choose
Reranker API (Cohere) Self-hosted (BGE) API for simplicity; self-hosted for data residency or high volume
Initial k 20 50 Higher k when recall is low; lower k when latency matters
Final n 3 5 3 for focused answers; 5 for complex questions needing more context
Score threshold None Minimum score (e.g., 0.3) Threshold to filter irrelevant results and trigger "I don't know"
Rerank all or skip Always rerank Skip for high-confidence retrieval Skip when top-1 bi-encoder score exceeds a high threshold (saves latency)

Common patterns

| Pattern | Description | | ------------------------------- | ------------------------------------ | ----------------------------------------- | | Retrieve many, rerank few | k=25 → n=5 | Common deployed default | | Conditional rerank | Skip if bi-encoder top-1 > threshold | Latency-sensitive paths | | Score threshold gate | Drop low rerank scores | Trigger "I don't know" | | Dedupe then rerank | One chunk per doc ID | Avoid wasting cross-encoder on duplicates | | Stack with late interaction | Hybrid → MaxSim → cross-encoder | Maximum precision pipelines |

Comparisons

Cross-encoder vs bi-encoder vs late interaction vs LLM judge

Method Scale Precision Latency
Bi-encoder Millions of docs Moderate Low
Cross-encoder rerank 20–50 pairs High Often ~100–300ms (illustrative; varies by hardware and model)
Late interaction (MaxSim) 50–200 docs High token binding Moderate
LLM-as-judge 5–10 pairs Highest Seconds; costly

Cohere Rerank vs bge-reranker vs Jina

Model Deployment Context Best for
Cohere rerank-v3.5 API 4096 tokens Fast integration, multilingual
bge-reranker-v2-m3 Self-hosted 8192 tokens Data residency, high volume
Jina Reranker v2 Both 8192 tokens Long chunks

Decision tree: reranker selection

Decision tree: choosing a reranker

flowchart TD
    A[Need reranking?] -->|Recall broken| B[Fix retrieval first]
    A -->|Yes| C[Data leaves VPC?]
    C -->|No| D[Cohere or Jina API]
    C -->|Yes| E[Self-host bge-reranker]
    E --> F{Long chunks?}
    F -->|Yes| G[bge-reranker-v2-m3 8k]
    F -->|No| H[MiniLM for speed]
    D --> I[Measure precision@3]
    G --> I
    H --> I

Do not add reranking until recall@k is acceptable — reranking cannot retrieve missing documents.

Compare retrieval infrastructure in Best Vector Databases: Qdrant vs Pinecone · Pinecone vs Weaviate.

Common Mistakes

  1. Passing too many documents to the reranker. Cross-encoders are slow. Reranking 100 documents adds seconds of latency. Retrieve 20–50, rerank to 3–5.

  2. Skipping reranking because retrieval "looks fine." Bi-encoder scores are poorly calibrated. A document at rank 1 with score 0.85 may be less relevant than rank 5 with score 0.78. Measure with precision@k, don't eyeball.

  3. Reranking before metadata filtering. Apply tenant and permission filters before reranking to avoid scoring documents the user shouldn't see.

  4. Not logging reranker scores. When answers are wrong, reranker scores tell you whether the right document was retrieved but scored low (reranker problem) or wasn't retrieved at all (retrieval problem).

  5. Using a reranker with mismatched language. English rerankers on multilingual content produce unreliable scores. Match reranker language to your corpus.

  6. Reranking without initial retrieval. Cross-encoders can't search a million documents - they're too slow. Always use bi-encoder retrieval first, then rerank.

Where It Breaks Down

Latency-sensitive applications - Reranking 25 documents adds 100–300ms (API) or 200–500ms (self-hosted CPU). For sub-second requirements, consider smaller rerankers or conditional reranking (only when initial confidence is low).

Very long documents - Cross-encoders have input length limits (512–8192 tokens). If retrieved chunks are 1024 tokens, the reranker may truncate, missing relevant content at the end.

Non-text content - Standard rerankers process text only. Images, tables, and code may need domain-specific rerankers or alternative scoring.

Diminishing returns with perfect retrieval - If your initial retrieval already achieves 95%+ recall@5 with high bi-encoder scores, reranking adds marginal value. Measure before adding complexity.

Cost at extreme scale - Cohere Rerank costs ~$1/1000 searches. At 1M queries/day, that's $30K/month. Self-hosted becomes cost-effective above ~100K queries/day.

When NOT to Use Re-ranking

Skip reranking when:

  1. Recall@k is below target — fix chunking, embeddings, or hybrid search first; reranking cannot find missing docs.
  2. Sub-200ms total latency is mandatory — cross-encoder adds 100–300ms; use conditional rerank or smaller models.
  3. Initial retrieval already achieves precision@3 > 0.95 — measure before adding complexity.
  4. Candidates exceed reranker context — 1024-token chunks in a 512-token reranker truncate relevant tail content.
  5. You cannot send document text to a third-party API — use self-hosted bge-reranker for sensitive corpora.

Prefer Late Interaction Retrieval when compositional token matching matters more than full cross-attention on a shortlist.

Running in Production

Best Practice

Best Practices - Instrument every stage, version embedding models, enforce access control at retrieval time, and evaluate on a fixed golden set before shipping changes.

Dimension Consideration
Scaling API rerankers scale automatically. Self-hosted: one GPU handles ~50–200 rerank pairs/sec. Batch score all candidates in one call.
Latency Illustrative ranges (25-document rerank): Cohere API often ~100–250ms; self-hosted GPU often ~50–150ms; self-hosted CPU often ~200–500ms. Budget against your SLA — actual latency depends on hardware, deployment architecture, corpus size, and candidate count.
Cost Cohere: ~$0.001/search. Self-hosted: GPU compute only. At 10K queries/day, API cost is ~$10/day - usually negligible vs LLM generation cost.
Monitoring Log reranker scores, rank changes (did reranking reorder results?), and latency. Alert on score distribution shifts.
Evaluation Measure precision@3 and nDCG with and without reranking. A/B test with live traffic. Benchmark on your own corpus and query distribution — published reranker scores are useful for comparison but should not replace evaluation on production-like workloads.
Security API rerankers send document text to third parties. Self-hosted for sensitive content. Apply metadata filters before reranking.

Important

Reranking is a common production pattern for RAG when initial retrieval recall is solid but precision@k is weak. Added latency is often ~100–300ms in typical deployments — measure precision@3 on your golden set and against your SLA before skipping it.

Concept guides

Rankings

Comparisons

Tools

If you understood this topic, read next:

Diagram: Reranking learning path

flowchart LR
    A[Hybrid Search] --> B[Re-ranking]
    B --> C[Retrieval Eval]
    C --> D[Late Interaction]
    D --> E[RAG]

Prerequisites: RAG · Embedding Models · Hybrid Search

Next topics: Retrieval Evaluation · Late Interaction Retrieval · Metadata Filtering

Interview Questions

  1. Why can't cross-encoders replace first-stage retrieval?

    • Expected: O(N) inference per query; too slow for millions of documents.
  2. What is retrieve-many rerank-few?

    • Expected: bi-encoder top-20–50 for recall; cross-encoder to top-3–5 for precision.
  3. Bi-encoder vs cross-encoder tradeoff?

    • Expected: independent encoding + ANN vs joint encoding + accurate scores at query time.
  4. When do reranker scores indicate retrieval vs ranking failure?

    • Expected: right doc missing = retrieval; retrieved but low rerank score = ranking/model mismatch.
  5. Why filter before reranking?

    • Expected: avoid scoring documents user cannot access; security and wasted compute.
  6. Cohere vs self-hosted bge-reranker?

    • Expected: API simplicity vs data residency and volume economics.
  7. How do you evaluate reranking impact?

    • Expected: precision@3, nDCG@5, end-to-end answer quality on golden set.
  8. Reranking vs late interaction?

    • Expected: cross-encoder full attention on shortlist vs MaxSim token matching; can stack both.

Key Takeaways

  • Reranking uses cross-encoders to precisely score query-document relevance after initial retrieval.
  • Retrieve many (20–50), rerank to few (3–5) — a standard deployed pattern.
  • Often one of the highest-ROI retrieval improvements after fixing recall@k.
  • Always apply metadata filters before reranking, not after.
  • Log reranker scores to diagnose retrieval vs ranking failures.
  • Example production models (current as of writing): Cohere Rerank (API) and bge-reranker-v2-m3 (self-hosted).

FAQs

What is the difference between retrieval and reranking?

Retrieval (bi-encoder) finds candidate documents quickly from a large corpus. Reranking (cross-encoder) accurately scores a small set of candidates. Retrieval optimizes recall; reranking optimizes precision.

How many documents should I rerank?

Retrieve 20–50, rerank to 3–5. The exact numbers depend on your eval metrics - increase initial k if recall is low, decrease final n if the LLM gets confused by too much context.

Is reranking worth the latency?

Often yes — many teams accept ~100–300ms of reranking latency when precision@3 measurably improves on their golden set. Users typically prefer a slightly slower correct answer over a fast wrong one, but validate on your own SLA and eval data.

Cohere Rerank vs bge-reranker?

Cohere: easier integration, no GPU needed, ~$0.001/search. BGE: free, self-hosted, data stays local. Similar quality. Choose based on ops preference and data sensitivity.

Can I use an LLM as a reranker?

Yes (LLM-as-judge), but it's 10–50x slower and more expensive than a dedicated cross-encoder. Use LLM reranking only for high-stakes queries where latency and cost are acceptable.

Should I rerank before or after metadata filtering?

After filtering. Apply tenant/permission filters during initial retrieval, then rerank the filtered candidates. Never rerank documents the user shouldn't access.

What if reranking makes results worse?

Rare, but possible if the reranker model doesn't match your domain. Evaluate on your test set. Try a different reranker model. Check if chunks are too long (truncation).

Can I cache reranker results?

Cache reranked results for identical queries (exact or semantic cache). Reranker scores are deterministic for the same query-document pairs.

Yes. Hybrid search improves recall (finding more relevant docs). Reranking improves precision (ranking them correctly). They solve different problems and complement each other.

How do I evaluate reranking impact?

Compare precision@3 and nDCG on your test set with and without reranking. Measure end-to-end answer correctness. A/B test in production with real user queries.

What is a reranker score threshold?

A minimum relevance score below which documents are excluded. If no documents exceed the threshold, return "I couldn't find relevant information" instead of generating from irrelevant context.

No. Reranking reorders candidates; it can't find documents that initial retrieval missed. Fix recall with hybrid search and better embeddings first, then add reranking for precision.

How do I choose between reranker models?

Run both Cohere Rerank and bge-reranker-v2-m3 on your golden test set. Compare precision@3 and nDCG@5. If scores are within 2%, choose based on deployment preference (API vs self-hosted). If one model clearly wins on your domain, use it regardless of deployment convenience.

What hardware do I need for self-hosted reranking?

A cross-encoder reranking 25 document pairs requires ~500MB GPU memory for bge-reranker-v2-m3. Throughput varies widely by hardware — illustrative ranges are ~50–200 rerank pairs/sec on a single GPU vs ~300–500ms per batch on CPU. Benchmark on your deployment.

Should I rerank before or after deduplication?

Deduplicate first. If initial retrieval returns five chunks from the same document, reranking all five wastes compute and crowds out diverse sources. Deduplicate by document ID, keeping the highest bi-encoder score per document, then rerank the deduplicated set.

Does reranking help with multilingual RAG?

Yes, but only if you use a multilingual reranker (for example, Cohere Rerank v3.5 or bge-reranker-v2-m3 at time of writing). English-only rerankers on multilingual content produce unreliable scores. Match the reranker language support to your corpus and query languages.

References

Further Reading

Next Topics

Learning Path

Continue Learning

Related Guides

Related Tools

ToolCategoryPurposeWebsiteBest For
Cohere
APICloud
LLMEnterprise NLP platform with strong embedding and reranking APIs for RAG.cohere.comProduction embeddings
Hugging Face Transformers
Python SDK
frameworksLibrary for using pretrained transformers in Python and beyond.huggingface.coModel fine-tuning
Qdrant
Open SourceAPI
Vector DBOpen-source vector database with filtering and hybrid search.qdrant.techRAG systems
Weaviate
MaintainedOpen SourceAPI
Vector DBOpen-source vector database with hybrid search and modules.weaviate.ioEnterprise search
Pinecone
PopularAPICloud
Vector DBManaged vector database plus Pinecone Nexus knowledge engine for agent RAG.pinecone.ioRAG systems
Voyage AI
APICloud
infrastructureSpecialist embedding and reranking models optimized for retrieval quality.voyageai.comHigh-quality retrieval
Jina AI
Open SourceAPI
infrastructureOpen multimodal embeddings and rerankers with self-host and cloud options.jina.aiOpen embeddings

Related Rankings

Related Comparisons