AI agents

Turning a Retrieval Curve Into a Go/No-Go Release Rule

Antonio Evans9 min read

A hand circles a point above a dashed threshold line on a pinned recall-versus-k curve while a colleague at a desk logs a waiver reason in a table with columns for change, threshold, confidence, decision and sign-off.
Key points

Key points

  1. 1A retrieval curve is a measurement, not a decision; it becomes a release rule only when the metric, threshold, confidence requirement and signer are fixed before the change is run.
  2. 2Set the minimum improvement from measurement noise: a small golden set produces wide intervals, so a lift of 0.02 on 40 queries is usually indistinguishable from zero.
  3. 3Require a confidence interval that excludes zero lift (or a probabilistic regression risk below a fixed cap) before a curve difference counts as improvement.
  4. 4Log every waived gate with the owner, the reason, the size of the shortfall and an expiry date, because waived gates that are never revisited are how quality decays silently.

Why a curve is not yet a rule

A retrieval curve plots a quality metric against a knob: chunk size, top-k, overlap, reranker cutoff, embedding model. It answers "what happens if I change the knob?" It does not answer "may I ship this?" Those are different questions, and teams that confuse them end up arguing about the shape of a line in a release meeting instead of applying a rule.

The reason the distinction matters is that retrieval failures are silent. A wrong chunk does not throw an exception; the application keeps returning fluent answers built on the wrong evidence, and nobody notices until a user reports a confidently wrong result weeks later (Welcome, Developer). An error log will never tell you that recall@10 fell from 0.81 to 0.74. Only a fixed evaluation set and a pre-committed rule will.

There is a second reason: curves are noisy. If you re-chunk a corpus and recall@10 moves from 0.742 to 0.751, you cannot tell from the curve alone whether the chunker helped or whether you drew a slightly easier sample of queries. The published work on release gating for RAG makes the point bluntly: point estimates alone are not a release decision, because evidence is incomplete and the metrics come from fallible judges (AGO AI Quality Gate).

So a release rule does three things a curve cannot. It fixes the metric and the margin in advance, it fixes how much confidence the margin needs, and it names who can say yes. Everything else in this article builds those three pieces and the audit trail around them.

Fix the metric, the query set and the top-k first

Before any threshold makes sense, pin down what you are measuring and on what. Three choices drive the rest:

The metric. Recall@k answers "of all the relevant chunks that exist, how many did we retrieve?" Precision@k answers "of the k chunks returned, how many were relevant?" (RAG Evaluation Simplified). For knowledge assistants where a missed chunk means an unanswerable question, recall@k is usually the gate metric and precision@k is the guardrail. Pick one primary metric per gate; two primary metrics invite the argument about which one wins.

The query set. You need a fixed golden set with expected evidence per query. Twenty to thirty hand-written pairs is enough to start catching regressions, and the value is that it never changes between runs (Welcome, Developer). If you want statistical confidence later, plan for a larger held-out split, because interval width scales with sample size.

The k. Recall@k is meaningless without a fixed k, and k interacts with everything downstream. Raising top-k from four to 10 pushed time to first token from 3.6 to 7.9 seconds in NVIDIA's enterprise retrieval sizing tests, while moving chunk size from 256 to 1,024 tokens took it from about 2.0 to 7.1 seconds (Splunk). If you gate on recall@10, you have committed to returning ten chunks, so the latency gate has to be written against the same k.

One useful insight the first search result rarely gives you: the optimal chunk size is not a constant across corpora, so do not carry a threshold across from a blog post. A multi-dataset sweep found 64 to 128 token chunks optimal for fact-based answer datasets, while 512 to 1,024 token chunks won on datasets needing broader context (Rethinking Chunk Size for Long-Document Retrieval). NVIDIA's experiments found page-level chunking best on average across its datasets but 1,024 tokens best on FinanceBench and 512 on earnings documents (NVIDIA). Your threshold has to be expressed relative to your own baseline, not an absolute score copied from someone else's corpus.

Set the minimum improvement from noise, not from hope

The threshold is the smallest improvement that counts as a win. It should be derived from how much your metric moves when nothing changes.

The practical procedure:

  1. Re-run the current configuration against the golden set several times with resampling (bootstrap over queries, or repeated splits) and record the spread of recall@k.
  2. Note the standard deviation of that spread. That is your noise floor.
  3. Set the threshold at roughly two noise floors, then sanity-check it against business cost. If a chunker change costs half a day of engineering and doubles your vector count, a lift smaller than the noise floor is not worth the risk.

A worked example. Suppose your golden set has 200 queries and your baseline recall@10 is 0.74. Bootstrapping gives a 95% interval of roughly plus or minus 0.05, that is, 0.69 to 0.79. A candidate chunker scores 0.76. That candidate is inside the noise band of the baseline, so the correct verdict is "no decision": you cannot distinguish it from no change. Now suppose a different candidate scores 0.81 with its own interval of 0.77 to 0.85 and a bootstrap distribution of the paired difference whose 95% interval is 0.02 to 0.13, excluding zero. That candidate clears a 0.03 threshold on the point estimate and clears the confidence test. Verdict: go, subject to sign-off.

Use paired resampling (resample queries, compute both configurations on the same resampled set, take the difference) rather than comparing two independent intervals. Paired differences are much tighter because the same hard queries are hard for both systems, and a gate built on unpaired intervals will reject real improvements or accept noise depending on which way you get the arithmetic wrong.

The published gate design that most closely matches this is the stratified beta-binomial gate, which computes a probabilistic regression risk, the probability that the new version's underlying quality is worse than the old by more than a margin, instead of comparing single numbers (AGO AI Quality Gate). You do not need that machinery to start; percentile bootstrap intervals over a fixed query set give you the same discipline with far less code. But whichever you pick, the gate rule must reference the interval, not the point estimate, or the threshold is decorative.

A decision table you can copy

The table below is a starting policy, not a universal benchmark. Calibrate the numbers to your own noise measurement and risk tolerance; the gate study cited above explicitly treats its thresholds as illustrative starting points (RAG QA Testing Guide).

OutcomeRecall@10 changeConfidence conditionLatencyVerdict
Clear winBeat baseline by at least the threshold (for example +0.03)Paired 95% interval excludes zeroWithin budget at the gated kShip, standard sign-off
Probable win, small sampleBeat thresholdInterval includes zero but point estimate clears it by 2xWithin budgetExtend the query set or run a shadow test; do not ship on this alone
FlatWithin plus or minus the thresholdAnyAnyNo change; do not ship for a retrieval reason
RegressionBelow baseline by more than the thresholdPaired interval excludes zero on the negative sideAnyBlock
Silent regressionAny dropAnyAnyBlock; investigate before merging
Guardrail breachAnyAnyp95 over budgetBlock unless waived with a logged reason
Not evaluableMissing traces or judge errorsNot measurableNot measurableTreat as blocked, not as a pass

The last row is the one most teams get wrong. When evidence is missing, the honest gate outcome is "not evaluable", not "pass by default". The AGO work calls this a four-state decision model, where missing data and judge errors are explicit outcomes rather than being averaged away as zeros (AGO AI Quality Gate).

Validate the judge before you trust the gate

If any part of the curve is scored by an LLM judge, the gate is only as good as the judge. This is where a lot of release rules quietly fail.

The numbers are sobering. On identical stratified samples of 1,200 RAG traces, a low-cost judge detected non-adherent answers barely above chance, with an AUROC of 0.603, while a stronger judge reached 0.783 and still ranged from 0.62 to 0.88 depending on the domain (AGO AI Quality Gate). A judge that outputs perfect protocol-shaped JSON can still be close to useless as a measuring instrument.

Three habits keep the judge honest:

  • Keep the judge prompt narrow and ask for a small ordinal scale (0, 1, 2) rather than 0 to 10, because wide scales produce noisy, inconsistent scores that look precise and are not (Welcome, Developer).
  • Ask for a one-sentence reason alongside the score, so a dropped number can be diagnosed without a manual re-run.
  • Meta-evaluate the judge on a labeled sample before it influences your release decision, and record the agreement figure in the gate policy.

Evaluation work in practice also separates retrieval metrics from generation metrics, so a bad answer can be traced to the retriever or to the generator rather than to a single fuzzy score (Confident AI). Your gate should name which half of the pipeline a regression lives in, or the signer will be asked to approve a fix they cannot scope.

Who signs off, and what to log when someone waives the gate

A gate with no named owner is a suggestion. Write the rule with three roles:

The release owner. One named engineer accountable for the RAG surface. They can approve a clear win and must block a regression. The name goes in the policy file, not in someone's memory.

The reviewer who can waive. A second named person, usually the tech lead or the product owner for that surface, who can waive a gate when the schedule justifies it. Two signatures for a waiver, one for a clean pass.

The policy owner. Whoever maintains the threshold and the query set, reviewed on a schedule, because a golden set that never changes quietly stops representing production traffic.

When a waiver happens, the log entry needs enough detail that a reader six months later can judge whether the decision was sound. At minimum:

  • the gate name and the metric with its value, baseline value and threshold
  • the size of the shortfall as a number
  • the confidence evidence (interval, sample size, judge agreement figure)
  • the reason in free text, written for a stranger
  • the waiver owner and the approving signer
  • the expiry date and the remediation ticket that closes it
  • the commit and the index or chunker configuration hashes that were deployed

Make the log machine-readable so it can be queried later. A minimal entry, as JSON:

{
  "gate": "retrieval.recall_at_10",
  "baseline": {"value": 0.74, "ci": [0.69, 0.79]},
  "candidate": {"value": 0.72, "ci": [0.67, 0.77]},
  "delta_ci": [-0.04, 0.01],
  "threshold": 0.03,
  "verdict": "waived",
  "reason": "Tightens chunk overlap; recall dip concentrated in 11 legal PDFs. Fix tracked in RAG-114.",
  "waiver": {"owner": "ana", "approver": "marcus", "expires": "2026-06-30"},
  "config": {"chunker": "recursive", "size": 512, "overlap": 100, "commit": "a91f2c3"}
}

Two rules make waivers safe rather than corrosive. First, waivers expire; an open waiver past its date is an incident, not a status quo. Second, a waiver that repeats more than twice for the same gate means the threshold or the system is wrong, and the policy owner must revisit it. The measured cost of weak gating is real: under simulated regression, a decision-grade gate profile cut unsafe promotion to between 22.2 and 35.1 percent, against 29.3 to 41.8 percent for a naive gate (AGO AI Quality Gate). Even a good gate lets some regressions through; the log is what lets you find them afterwards.

Wiring the rule into the pipeline

The rule only works if it runs automatically on every candidate change. Put it in CI as a job that builds the candidate index, runs the fixed query set, computes the paired interval and writes a verdict artifact.

import random
from statistics import mean

def paired_bootstrap_ci(baseline, candidate, iters=2000, alpha=0.05, seed=7):
    random.seed(seed)
    diffs = []
    n = len(baseline)
    for _ in range(iters):
        idx = [random.randrange(n) for _ in range(n)]
        b = mean(baseline[i] for i in idx)
        c = mean(candidate[i] for i in idx)
        diffs.append(c - b)
    diffs.sort()
    lo = diffs[int(alpha / 2 * iters)]
    hi = diffs[int((1 - alpha / 2) * iters)]
    return lo, hi

# per-query recall@10, aligned by query id
lo, hi = paired_bootstrap_ci(baseline_recall, candidate_recall)
verdict = "go" if lo > 0.03 else "block"

Keep the ingest side deterministic so the comparison is fair. Chunk sizes set in characters behave differently from token counts, because a 512-character window is anywhere from 100 to 400 tokens depending on the tokenizer, so a size tuned for one model silently truncates or wastes context on another (ChunkRank). Pin overlap too, since repeats from overlap cost extra vectors; the common guidance holds overlap to 10 to 20 percent of the chunk (The AI Engineer).

One more check for chunker updates specifically: when you change chunk boundaries, the context your generator sees changes, so gate both halves. Chunking sets a ceiling on answer quality that no later stage can recover (The AI Engineer), and the context window utilization a chunk occupies trades against irrelevant text in the prompt (Context Window Utilization). A chunker that raises recall@10 but fills the window with redundant overlap can still hurt end-to-end answers, so run a small faithfulness check as a secondary gate.

If you are optimizing the retrieval path itself, budget latency as a first-class gate: define the retrieval allowance in milliseconds, allocate it by stage, and review p95 rather than the median, because tail latency defines the user experience (Latency Budgets for Memory Retrieval). Trace requests end to end rather than adding per-stage percentiles together, since slow stages may land on different requests (MLflow). When your gate logic needs to call several models for judging and for the candidate pipeline, one OpenAI-compatible endpoint for text, embedding and image models keeps the CI bill predictable; Quanta Inference is one option for that (Quanta Inference).

FAQ

FAQ

How many queries do I need before a threshold is meaningful?

Enough that the bootstrap interval on your metric is narrower than the threshold you intend to set. Start with twenty to thirty hand-written pairs to catch obvious regressions, then grow toward a few hundred held-out queries for any decision you intend to defend statistically. If your interval is wider than your threshold, the gate cannot pass a candidate on confidence alone, and the honest verdict is "extend the set".

What if my candidate improves recall but gets slower?

Treat latency as a separate gate with its own threshold and its own signer, rather than mixing it into the retrieval score. The two interact: raising top-k or chunk size raises time to first token, and the effects multiply rather than add (Splunk). A change that wins on recall and loses on p95 latency needs an explicit trade decision, logged like any other waiver.

Can I just use a fixed percentage improvement instead of confidence intervals?

You can, and many teams start there, but a fixed percentage with no interval will accept noise when the query set is small and reject real gains when the noise is high. The safer pattern is: threshold on the point estimate, interval on the paired difference, and a rule that both must pass. The gate literature is explicit that a point estimate alone is not a release decision (AGO AI Quality Gate).

How do I handle a chunker update that shifts scores for one document type only?

Stratify. Compute the metric per document type or per query category, and gate on the strata that matter most, because chunking sensitivity varies by corpus and even within similar financial documents the best size differs (NVIDIA). A judge also varies by domain, so per-stratum intervals are more honest than one pooled number (AGO AI Quality Gate). A regression confined to legal PDFs can then be blocked without freezing a win for support content.

Who should own the gate policy long term?

Assign it to whoever owns the retrieval surface's quality, usually the tech lead for the RAG application, with a scheduled review of the threshold, the query set and the judge agreement figures. Keep the policy in version control next to the evaluation harness so a change to the rule is itself reviewable. If your team would rather have an outside pair of eyes on the gate design and the query set, a consulting call with Quanta experts who build retrieval systems daily is a reasonable next step (Quanta Experts).

Sources

Sources

  1. How to Know Your RAG Changes Actually Helped
  2. AGO AI Quality Gate: Evidence-First Release Decisions for ...
  3. RAG Evaluation Simplified, Part 2: Deep Dive into Recall ...
  4. Advanced Chunking Techniques: What The Benchmarks ...
  5. Rethinking Chunk Size for Long-Document Retrieval
  6. Finding the Best Chunking Strategy for Accurate AI Responses
  7. RAG QA Testing Guide for Retrieval, Generation, and ...
  8. RAG Evaluation: Metrics, CI/CD, and Production Monitoring
  9. ChunkRank: Model-Aware Text Chunking and Abstention- ...
  10. What is Chunking? - The AI Engineer - Substack
  11. Introducing a new hyper-parameter for RAG: Context ...
  12. Latency Budgets for Memory Retrieval
  13. One post tagged with "latency trade-offs"
About the author

About the author

Antonio Evans
Antonio Evans

Antonio Evans is the founder of Quanta Intelligence and a fractional CTO who builds HIPAA-ready AI systems for health and life-science companies. Before that he was technical co-founder of FriendsEAT for twenty years, CEO of Socialdraft, and a data engineer at IBM. Antonio lives with his dog Santino in Lisbon, Portugal.

All articles