Skip to content
RAG Explained Better

Why Your RAG Pipeline Is Slow

A stage-by-stage latency budget with measured numbers, and the two stages that are almost always the problem.

A slow RAG pipeline means end-to-end query latency exceeds the budget users feel — the sum of embed, retrieve, rerank, prompt assembly and generation, not a single mysterious delay. It is not a wrong-answer failure (see wrong chunk); the answer may be fine and still arrive too late. Before you swap models or rebuild the index, instrument per-stage spans and read p95, not the average. The mean hides the slow tail users complain about.

In production, generation is often the largest wall-clock contributor, and retrieval-side overhead compounds fast once multi-stage search and reranking enter the path — that is the pattern Echelon Edge documents in its 2026 pipeline breakdown. The two stages that almost always dominate the budget are LLM generation and reranking. Everything else on this page is how to prove which one (or which multiplier) is yours.

First, which stage is eating the budget?

A slow RAG pipeline has five distinct causes, and each has a different fix. Applying the wrong fix — dropping top-k when the problem is an always-on cross-encoder, or tuning HNSW when generation dominates — costs time and changes nothing. Most optimisation guides walk tips in a bag: cache, then ANN, then stream, then hope. The faster path is differential diagnosis: start from the one symptom (users wait), and run the single span measurement that rules each cause in or out. Each row below is a measurement you run before you change code.

The five causes of a slow RAG pipeline, the span that isolates each, and the matching fix
CauseWhat you seeDetection (run this first)Fix
1 · Generation dominatesLong wait for tokens; upstream spans look finegenerate_ms largest share of e2eStreaming / shorter context
2 · Reranker always onLatency rises when candidate count risesrerank_ms large; scales with kReranking cost
3 · Oversized top-kBigger k helps quality, then p95 collapsesΔ(e2e) when k is halvedChoosing top-k
4 · Untuned ANN / cold retrieveRetrieve is slow even with no rerankretrieve_ms dominates pre-generateHNSW
5 · No cache on repeatsPopular queries as slow as novel onescache hit-rate ≈ 0 on repeat trafficMonitoring + cache

Why does p95 matter more than average latency?

Users feel the slow tail. p95 latency is the threshold below which 95% of requests complete — Jim Allen Wallace (Redis, 2026) states that definition plainly, and notes that a healthy-looking average can coexist with a meaningful share of much slower requests. In RAG, a single user query often fans out across an embedding API, a vector store, a reranker and an LLM; Redis’s write-up of Google’s Tail at Scale work is the reason those rare slow hops become common at the frontend. Budget and alert on p95 (and p99 under high QPS). Where those alerts live in a production stack is monitoring RAG in production.

Where does the time go in a RAG pipeline?

Query-time RAG is a sum of stages. The table below is a published typical-range budget, not a promise for your corpus or cloud region. Echelon Edge (2026) publishes these stage ranges in its pipeline breakdown; your measured spans will differ — that is the point of the diagnosis table above. A second published example plan (Bhagya Rana, 2025) aims for roughly 1.2 s to first useful tokens with its own stage allotments; treat that as one author’s plan, not a site-wide target.

Five query-time RAG stages on one millisecond scale, from Echelon Edge’s 2026 published typical ranges. Query embed, turning the question into a vector, 20 to 100 milliseconds. Retrieval, ANN or hybrid search over the index, 10 to 150 milliseconds. Reranking, scoring top candidates with a cross-encoder, 80 to 300 milliseconds. Prompt assembly, deduping, ordering and budgeting tokens, 20 to 80 milliseconds. LLM generation, prefill plus decode, 500 milliseconds to 5 or more seconds — an order of magnitude longer than every other stage, with the bar cut off because the published range has no upper bound.
On one scale the ranking of suspects is unarguable: generation’s published range sits an order of magnitude above every retrieval-side stage, and reranking is the only other stage that grows with the candidate count (Echelon Edge, 2026 — typical ranges, not an SLO for your corpus or region).
Published typical stage ranges for query-time RAG (Echelon Edge, 2026) — measure your own
StageWhat it doesPublished typical rangeSource
Query embedTurn the question into a vector20–100 msEchelon Edge (2026)
RetrievalANN / hybrid search over the index10–150 msEchelon Edge (2026)
RerankingScore top candidates with a cross-encoder80–300 msEchelon Edge (2026)
Prompt assemblyDedupe, order, budget tokens20–80 msEchelon Edge (2026)
LLM generationPrefill + decode tokens500 ms–5+ sEchelon Edge (2026)

Read the table as a ranking of suspects, not as your SLO. Generation’s published range sits an order of magnitude above the retrieval stages; reranking is the retrieval-side stage whose cost grows with the number of candidates. Those are the two stages this page treats as “almost always the problem.” The measured trade for rerankers is at what reranking costs you in latency; the index knobs behind the retrieval row are at HNSW.

Is the language model the reason it feels slow?

Often yes — generation is the primary wall-clock bottleneck in Echelon Edge’s 2026 breakdown, with a published typical range of 500 ms to 5+ seconds depending on model size, output length and hardware. Upstream stages can look healthy while users still wait on tokens.

Symptom

Time to first token is high, or the answer drips slowly. Embed and retrieve spans look fine in the trace.

Detection

Attribute wall-clock to stages. If generate_ms (or TTFT + decode) is the largest share of end-to-end latency, generation dominates — not the vector search.

Cause

Autoregressive decoding plus a long prompt: every extra context token taxes prefill before the first token appears.

Fix

Shorten context, cap max_tokens, route easy queries to a smaller model, and stream tokens so perceived latency drops even when full generation does not. Streaming mechanics live at streaming RAG responses.

Does the reranker make RAG slow?

It can. Reranking improves relevance, but unlike ANN retrieval it scores candidates more carefully and its cost scales with how many you send it. Echelon Edge (2026) puts a typical reranking range at 80–300 ms; AI Agent Studio (2025) claims running a cross-encoder on every query can add 300–800 ms — cite that as their published claim, then measure yours.

Symptom

Relevance improved after you added a cross-encoder, and wait time jumped. Latency rises when you raise the candidate count.

Detection

Log rerank_ms. If it is large and grows roughly linearly when you double candidates, the reranker is the bottleneck — not “retrieval” as a whole.

Cause

Cross-encoders evaluate query–document pairs; work scales with candidate set size, and always-on routing pays that cost on easy queries too.

Fix

Shrink the candidate set, use a lighter or conditional reranker, and cache scores for repeated queries. The measured accuracy-for-latency trade is at what reranking costs you in latency.

Is top-k making the pipeline slower?

Oversized k is a multiplier, not a single slow call. Echelon Edge (2026) calls this the context tax: more chunks mean more rerank work and a larger prompt for the model to prefill. Raising k can look like a quality win until p95 collapses.

Symptom

Answers improve when you raise top-k, then the system feels sluggish. Prompt token counts climb with every “just in case” chunk.

Detection

Halve k on a labelled sample. If end-to-end latency drops sharply while answer quality holds, oversized k was multiplying rerank and generation — measure the quality curve rather than guessing.

Cause

Candidate count and prompt size expand the workload of every later stage; latency is multiplicative across the path, not a simple sum of independent costs.

Fix

Discipline top-k and stop sending whole pages when a paragraph will do (Jamie Maguire, 2026). The measured curve between k, quality and cost is at how many chunks should you retrieve.

Is vector search itself the bottleneck?

Sometimes. When retrieve_ms dominates before generation — cold indexes, brute-force search, cross-region hops, or an untuned ANN — the vector stage is the problem. Echelon Edge (2026) publishes a typical retrieval range of 10–150 ms; outliers above that range are where index work pays off.

Symptom

Retrieve is slow even with reranking disabled. First queries after idle are much slower than warm ones.

Detection

If retrieve_ms dominates the pre-generate span, and changing ANN parameters (for HNSW, ef_search) moves that span, you have an index/search problem — not a generation problem.

Cause

Flat search, cold caches, distant regions, or ANN settings that trade too much latency for recall.

Fix

Use ANN (commonly HNSW), co-locate embedding and index, and tune search parameters against a recall floor. Popular vector stores for this work include Weaviate, Pinecone, Qdrant and Milvus — pick on your constraints, then measure. Graph-parameter depth is at HNSW.

Would caching fix the slow queries?

Caching fixes repeated work. It does not fix unique long-tail questions. Devot (2026) argues for caching retrieval candidates (top-k keyed by a normalized query fingerprint, versioned by embedding batch) rather than only full answers — paraphrases miss an answer cache and still pay for search.

Symptom

Popular or repeated questions are as slow as novel ones. p95 spikes after deploys until the cache warms (Devot, 2026).

Detection

Measure cache hit-rate on traffic that should repeat. If it sits near zero, and identical normalized queries take the full path every time, missing cache is the cause.

Cause

No query or retrieval cache — or an answer-only cache that misses paraphrases and embedding-version changes.

Fix

Cache retrieval candidates and embeddings with TTLs and selective invalidation; watch hit-rate beside p95 in production monitoring. Long-tail unique queries still need the other four fixes.

How do you measure which stage is slow?

Rather than reason about the five causes one at a time, wrap each stage and print the milliseconds. Given a query path you already have, this logs rewrite, retrieve, rerank, assemble and generate separately so you can match a row in the diagnosis table. It depends only on the Python standard library.

Before you trust the numbers

Run this against your own stack. The published ranges in the budget table are typicals from named sources — not universal constants. Aggregate spans at p50 and p95 offline; do not optimise from a single warm request.

measure_rag_latency.py python 3.11
import time
from contextlib import contextmanager

@contextmanager
def span(name, log):
    """Append (name, elapsed_ms) when the block exits."""
    t0 = time.perf_counter()
    try:
        yield
    finally:
        log.append((name, (time.perf_counter() - t0) * 1000))

def answer(query, *, rewrite, retrieve, rerank, assemble, generate):
    """Return (result, timeline) with one ms row per stage.

    Pass callables you already use in production. No target ms are hard-coded —
    compare timeline entries to each other and to your p95 history.
    """
    timeline = []
    with span("rewrite", timeline):
        q = rewrite(query)
    with span("retrieve", timeline):
        candidates = retrieve(q)          # first-stage top-k
    with span("rerank", timeline):
        top = rerank(q, candidates)       # optional; no-op if unused
    with span("assemble", timeline):
        ctx = assemble(top)
    with span("generate", timeline):
        result = generate(q, ctx)
    return result, timeline

# Example: print which stage dominated one request
# result, timeline = answer(...)
# for name, ms in timeline:
#     print(f"{name}: {ms:.1f} ms")
# print("dominant:", max(timeline, key=lambda row: row[1])[0])

The script is deliberately transparent: each block is one row of the detection table above. It reports where the time went; it does not invent a target budget for you. In production, the same seams become traces and p95 alerts — wire that at monitoring.

What is RAG latency?

RAG latency is the end-to-end time from the user query to a usable answer — the sum of query embedding, retrieval, optional reranking, prompt assembly and LLM generation, plus network hops between them. It is a wall-clock problem, not a wrong-answer problem: the answer can be correct and still arrive too late.

Why does p95 matter more than average latency for RAG?

Users feel the slow tail. p95 is the threshold below which 95% of requests finish (Redis, Wallace 2026). A healthy-looking average can hide a slow 5%. RAG queries fan out across embedding, vector search, reranking and generation, so rare slow hops become common at the frontend. Budget and alert on p95, not the mean.

Which two stages usually make a RAG pipeline slow?

LLM generation and reranking. Generation often dominates wall-clock time (Echelon Edge 2026 publishes a typical range of 500 ms to 5+ seconds). Reranking is the retrieval-side stage whose cost scales with candidate count (typically 80–300 ms in that same breakdown). Prove which one with per-stage spans before changing code.

Does adding a reranker always make RAG slower?

Only when it runs on every query with a large candidate set. Cross-encoder cost scales with how many documents you score. Shrink candidates, use a lighter or conditional reranker, or cache scores. The measured accuracy-for-latency trade is at /reranking/cost.

How many chunks should I retrieve before latency suffers?

There is no universal number — measure it. Oversized top-k multiplies rerank work and prompt prefill (the context tax). Halve k on a labelled sample; if end-to-end latency drops sharply while quality holds, k was the multiplier. The quality curve lives at /retrieval/top-k.

How do you monitor RAG latency in production?

Emit per-stage spans on every request, aggregate p95 (and p99 under high QPS), and alert when p95 crosses your threshold or when cache hit-rate collapses after a deploy. Pair latency with retrieval quality and cost. The production watchlist is at /production/monitoring.