A RAG demo over 50 documents works on the first try. The same architecture over 5 million documents fails in ways the demo never hinted at: retrieval precision collapses, latency balloons, and the index costs more to keep fresh than to build. Scale is not more of the same; it is a different problem. This is a pattern catalog for RAG that holds up under real corpus size and query volume, covering chunking, hybrid retrieval, reranking, and the freshness and cost tradeoffs that decide whether the system survives production.
Scale breaks the naive RAG that demos so well
The canonical RAG tutorial is deceptively simple: embed your documents, store the vectors, embed the query, pull the top-k nearest, stuff them into the prompt. Over a few dozen documents it works on the first attempt, and that early success convinces teams the architecture is solved. It is not. At a few dozen documents almost any chunk is relevant because there is so little to be wrong about. At a few million, the same top-k pull returns near-duplicates, stale versions, and semantically-close-but-wrong passages, and the model dutifully reasons from whatever it was handed.
Three things break as the corpus grows. Precision falls, because with millions of vectors the k nearest by cosine similarity are no longer the k most useful. Latency climbs, because exact search over a large index is slow and approximate search trades recall for speed. And freshness becomes a running cost, because a corpus that changes daily needs continuous re-embedding and re-indexing that a static demo never had to pay for. Designing for scale means treating retrieval quality, latency, and freshness as an explicit budget, not as properties you get for free. The mistake is assuming the demo architecture is a smaller version of the production one. It is not. The production system is a different machine that happens to share a first step, and the layers you add to reach it, hybrid search, reranking, metadata filtering, incremental ingestion, are not optimizations bolted on later but the load-bearing structure. Teams that skip them do not get a slower version of good RAG; they get a fast version of confidently wrong RAG.
Layer the retrieval stack instead of trusting one hop
Robust RAG at scale is not a single vector lookup; it is a pipeline where each stage cheaply narrows the candidate set and the expensive, accurate stages run only on what survives. The pattern below is the workhorse for large corpora, and each layer earns its place by improving precision or controlling cost.
| Layer | Job | Typical setting | Why it matters at scale |
|---|---|---|---|
| Chunking | Split docs into retrievable units | 300 to 500 tokens, 10 to 15% overlap | Oversized chunks dilute relevance; tiny ones lose context |
| Hybrid retrieval | Combine vector and keyword search | Dense top-50 plus BM25 top-50, fused | Vectors miss exact terms; keywords miss paraphrase |
| Reranking | Reorder candidates by true relevance | Cross-encoder over the top 100 to top 8 | The single biggest precision gain per dollar |
| Metadata filtering | Constrain by tenant, recency, permission | Pre-filter on workspace_id and date | Enforces isolation and cuts the search space |
| Context assembly | Pack the winners into the prompt | Dedupe, order by score, cite IDs | Near-duplicates waste the context window |
Consider a corpus of 5 million chunks. Naive dense top-8 might land the right passage in position one about 60 percent of the time. Add hybrid retrieval to pull 100 candidates, then a cross-encoder reranker to reorder down to the final 8, and precision-at-1 commonly rises past 85 percent while adding only 80 to 150 milliseconds. The reranker is the highest-leverage layer: it sees just 100 candidates, so it can afford an expensive model that the first-stage retriever, scanning millions, never could. That asymmetry is the whole trick: cheap and approximate at the wide end, expensive and precise at the narrow end. A first-stage retriever that must touch 5 million vectors has a strict compute budget per candidate, so it stays coarse; the reranker, handed only 100 survivors, can spend far more per item and still finish in under 150 milliseconds. Ignore that division of labor and you either pay too much scanning the whole corpus with an expensive model or accept poor precision from a cheap one across the board.
Build the pipeline stage by stage and measure each
- Chunk by semantic boundary, not by fixed character count. Split on headings and paragraphs, target 300 to 500 tokens, and add 10 to 15 percent overlap so a fact that straddles a boundary survives in at least one chunk.
- Run hybrid retrieval from day one. Pull dense top-50 and BM25 top-50 in parallel and fuse them, so a query with a specific product code or error string is not lost by pure semantic search that paraphrases everything.
- Add a cross-encoder reranker over the top 100 candidates before you touch anything else. It is the largest precision gain per dollar in the entire stack, and it runs on a small enough candidate set to stay fast.
- Pre-filter on workspace_id and permissions before the vector search, not after. This enforces multi-tenant isolation as a retrieval property and shrinks the search space, which speeds every query.
- Instrument retrieval quality directly. Log the retrieved IDs and scores, sample answers weekly, and measure precision-at-k against labeled cases, so you can tell whether a bad answer came from bad retrieval or bad generation.
The five ways RAG breaks at scale
- Chunks too large. A 2,000-token chunk buries the relevant sentence among nine irrelevant ones and dilutes the embedding. Fix: target 300 to 500 tokens so each vector represents one coherent idea.
- Pure vector search. Dense retrieval alone misses exact identifiers, acronyms, and rare terms. Fix: fuse with BM25 keyword search so exact-match queries still land.
- No reranking. Trusting the first-stage top-k means the best passage often sits at rank 12, outside the window. Fix: rerank the top 100 down to the final few with a cross-encoder.
- Stale index. A corpus that changes daily but re-embeds monthly serves confident answers from deleted or superseded documents. Fix: run incremental ingestion on a cron and track a freshness lag metric.
- Retrieval-blind debugging. When an answer is wrong, teams blame the model without checking what was retrieved. Fix: log retrieval IDs and scores on every answer so you can see whether the context was even correct.
Harden your RAG pipeline this quarter
- Re-chunk to 300 to 500 tokens on semantic boundaries with modest overlap, and re-embed.
- Add BM25 keyword retrieval alongside your vector search and fuse the results.
- Insert a cross-encoder reranker over the top 100 candidates before context assembly.
- Pre-filter every query on workspace_id and permissions, ahead of the vector lookup.
- Log retrieval IDs and scores on every answer and track a freshness lag metric on the index.