DevelopmentSenior

RAG Architecture

Retrieval-augmented generation (RAG) answers questions about data a model was never trained on: find the relevant passages first, then put them in the prompt. Requiring the answer to come from those passages makes RAG a search system with a language model on the end, which is why almost every wrong answer is a retrieval failure rather than a generation one. The page opens with the twenty-four-line build checklist, then nine symptoms and where each is actually fixed, the two pipelines, how to measure retrieval on its own, the permission problem that turns a demo into an incident, the alternatives, and five documented failures.

Two pipelines
Indexing and querying
Most failures
Retrieval, not generation
Access control
Belongs in the index

The RAG build checklist

Here is the whole checklist first, because it is the thing worth having open during a design review rather than after an incident. It is numbered so a line can be cited: "we have not done 4.1" is a decision somebody can schedule, where "the permissions need thinking about" is not. Most RAG prototypes reach a demo having done groups 2 and 5 and none of 1, 4.1, 6 or 7 — and every one of those omissions surfaces later as a class of failure rather than as a bug.

RAG is two independent pipelines that share only the index. The indexing pipeline runs when documents change: it splits them into chunks along their structure, turns each chunk into a vector, and stores it with its metadata and access rules. The query pipeline runs on every question: it searches the index, narrows the candidates by reranking, and passes only the best few into the prompt so the answer can cite them. Because the model can only answer from what reached the prompt, almost every wrong answer is a retrieval failure rather than a generation one — which is why retrieval is measured on its own before any answer is judged.
  1. 1.Sources and scope

    1. The corpus is an explicit list of sources, not "everything the crawler could reach".
    2. Every source has a named owner who can be asked whether a document belongs in there.
    3. Each source’s access rules can be expressed per document. A source where they cannot is out of scope.
  2. 2.Chunking

    1. Split on document structure — a heading and its section, a table with its caption, a function with its docstring.
    2. Every chunk carries the document title and the section path, so a fragment still says what it is about.
    3. Every chunk has a stable id that survives a reindex, so an answer can cite it and a log can name it.
    4. Tables, code blocks and lists are not cut in half.
  3. 3.Embedding and index

    1. One for documents and questions, and its identity is recorded with the index.
    2. Changing the embedding model means a full rebuild, and there is a written procedure for doing it.
    3. The index stores access rules and freshness metadata beside each chunk, not in a separate system.
  4. 4.Retrieval

    1. Permission filtering runs before the similarity search, so a forbidden document is never a candidate.
    2. Keyword search runs alongside vector search and the two result lists are merged.
    3. Retrieve widely, rerank the candidates, and pass only the best few into the prompt.
    4. on a labelled question set is measured and tracked as a number that moves.
  5. 5.Generation

    1. The prompt says to answer only from the supplied context, and what to say when it does not contain the answer.
    2. The answer returns the chunk ids it used, as data rather than as prose.
    3. An answer citing nothing, or citing a chunk whose text does not support it, is refused rather than published.
  6. 6.Freshness and deletion

    1. Updates are incremental and keyed by document id, so an edit replaces a chunk rather than duplicating it.
    2. Deletions are handled explicitly, and a withdrawn document leaves the index the same day.
    3. There is a stated, deliberate answer to "how stale is this allowed to be?" and somebody agreed to it.
    4. Re-indexing a source whose permissions changed is a routine scheduled job, not an incident response.
  7. 7.Operations

    1. The index version is part of what is deployed, alongside the prompt version and the model version.
    2. What was retrieved is logged with every answer, so a complaint from last week is reproducible.
    3. A full rebuild is and can be run on demand without restoring from a backup.

Nine symptoms and where each one is fixed

When a RAG system answers badly, the instinct is to work on the prompt. It is almost always the wrong end. If the passage containing the answer never reached the prompt, no instruction can recover it — the model was asked to answer from material that did not contain the answer, and it did the only thing it can do. So the first diagnostic is mechanical: look at what was retrieved. This table is that lookup, done in advance.

SymptomUsual causeWhere to fix it
Confident answer, invented detailThe passage was never retrieved, and the prompt gave no way to say so.Retrieval, plus 5.1 — an explicit "answer only from the context, otherwise say you do not know".
Right document, wrong sentenceChunks are too large, so the relevant line is buried among paragraphs of noise.Smaller structural chunks (2.1) and a reranking pass over the candidates (4.3).
Exact identifiers never foundVector similarity blurs codes, SKUs and names into their neighbours.Hybrid search (4.2) — run keyword retrieval alongside and merge the two result lists.
A fragment that reads as if it is about something elseThe chunk lost the heading that gave it a subject, so "this" no longer refers to anything.Carry the title and section path into the chunk text (2.2). It is the cheapest line on the list.
Stale or withdrawn content quotedThe index was built once and never reconciled with edits and deletions.The indexing pipeline: incremental updates keyed by document id (6.1), deletions included (6.2).
Good answers, unusable latencyToo many chunks retrieved and every one of them sent to the model.Retrieve widely, rerank, then pass only the few best into the prompt (4.3).
A correct answer from a document this user may not openPermissions were applied to the results rather than to the query.Filter before the similarity search (4.1). This is the one row that is an incident, not a defect.
Quality fell off a cliff after an infrastructure changeThe embedding model changed and the index was not rebuilt, leaving two incomparable vector spaces.A full rebuild (3.2), and recording the embedding model with the index so it cannot happen quietly (3.1).
Nobody can reproduce a complaint from last weekThe retrieved set was never logged, so only the answer survives and it explains nothing.Log the chunk ids with every answer (7.2). Without it every quality discussion is an opinion.

Two pipelines, not one feature

RAG is drawn as a single arrow and built as two independent systems that run on completely different schedules. The indexing pipeline runs when documents change: it loads them, splits them into chunks, turns each chunk into a vector, and writes it to a store along with its metadata. The query pipeline runs on every user question: it embeds the question, retrieves candidate chunks, narrows them down, assembles a prompt and calls the model. Treating them as one thing is why the second week of a RAG project is usually spent discovering that reindexing was never designed — checklist group 6 exists because that discovery is so reliable.

An embedding is the mechanism that makes the first pipeline useful. A model converts a piece of text into a list of numbers positioned so that texts with similar meaning land near each other, which is why a question about "cancelling a subscription" can find a passage that says "terminating your plan" with no word in common. The same embedding model must be used for documents and for questions, and changing it means rebuilding the entire index — vectors from two different models are not comparable, and mixing them produces retrieval that is quietly, unfixably wrong.

Chunking is the decision with the most consequences and the least attention. Cut the page whole and the answering sentence arrives buried in paragraphs that dilute what the model reads. Cut it into fixed-size slices and the sentence wins the similarity match having lost the subject that made it mean anything — a fragment starting “this does not apply to trial accounts” no longer says what “this” was. Cut on the document’s own structure — a heading and the section under it, a table with its caption — and carry the document title and section path into every chunk, and the same sentence arrives with the context that makes it usable. The third change is the cheapest of the three and the one most often skipped.

Chunking is the decision with the most consequences and the least attention, and the diagram above is the whole argument for checklist group 2. Chunks that are too large bring irrelevant text along with the answer and dilute what the model is reading; chunks that are too small win the similarity match and then turn out to be missing the sentence that made them meaningful. What works better than any fixed size is splitting on the document structure — a heading and the section beneath it, a table with its caption, a function with its docstring — and carrying the document title and section path into each chunk, so a fragment that starts "This does not apply to trial accounts" still says what "this" was.

Measure retrieval before you judge the answer

Retrieval is something you evaluate on its own, with its own numbers, before any answer is graded. Build a set of real questions and mark, for each, which chunks actually contain the answer. Then measure how often the right chunk appears anywhere in the top k results at all — recall is the number that matters, because a chunk that was not retrieved cannot be rescued later, whereas an extra irrelevant chunk usually only costs tokens. Track it as a number that moves when you change chunking, the embedding model or the value of k, and you have converted an argument about quality into an experiment.

One question narrowing from a corpus to the four passages that actually reach the model, with each stage a different job done by a different tool. The permission filter runs first, on metadata stored with each chunk, so a document the reader may not open never becomes a candidate at all. Vector search and keyword search then run together and merge, because embeddings are strong on meaning and weak on exactness while keyword search is the opposite — an error code or a surname is precisely where one wins and the other blurs. A reranker reads the question against each candidate and scores it properly. Retrieving thirty and passing the best four is consistently better than retrieving four directly: the cheap wide net and the careful narrow judgement cannot be the same pass.

Reranking is the step that resolves most of the middle of the symptom table. Retrieval is tuned to be fast and generous, so it returns candidates that are roughly relevant; a reranker is a smaller model that reads the question and each candidate together and scores how well it actually answers. Retrieving thirty candidates and passing the best four to the model is consistently better than retrieving four directly, because the cheap wide net and the careful narrow judgement are different jobs done by different tools — and the funnel above is the shape that follows from taking that seriously.

One practical note on building that labelled question set, because it is the part teams put off. It does not have to be large and it must not be invented: take the questions people actually asked, from support tickets, search logs or the first weeks of the assistant itself, and mark the answering chunk by hand. Fifty of those are worth more than five hundred written by whoever had an afternoon, because the invented ones are phrased the way the person who built the index would phrase them, and that is precisely the query the index already handles.

The correct answer that is the incident

The failure that ends careers is not a wrong answer, it is a correct one. A RAG index built by crawling everything the crawler could reach will happily answer a question with a passage from a salary review, a legal draft or another customer’s ticket — the retrieval worked exactly as designed, the ranking was good, and the answer is accurate. There is no quality metric on this page that would have caught it, which is why permissions are a design decision made before the first document is ingested rather than a filter added when somebody notices.

A RAG index built by crawling everything the crawler could reach will happily answer a question with a passage from a salary review or another customer’s ticket, and the retrieval will have worked exactly as designed. Filtering the results afterwards is the arrangement that looks correct in review and leaks anyway: the restricted document was scored, counted and timed, and all three are observable from outside. Storing the access rules with each chunk and filtering before the similarity search is the only version of this that is a boundary rather than a curtain — the document is never a candidate, so there is nothing to strip and nothing to infer. Re-running an ingest over a source whose permissions changed is then a routine operational task rather than an afterthought.

Store the access rules with each chunk, and filter by the current user before the similarity search rather than after, so a document the user cannot see is never a candidate. Filtering the results afterwards leaks through relevance scores, counts and latency — all three are observable, and a determined user can learn that a document exists, roughly what it is about and when it changed, without ever seeing a line of it. Then treat re-running an ingest over a source whose permissions changed as a routine operational task: a person who left a project keeps their access in the index until somebody reruns the job, and "until somebody reruns the job" is not an access policy.

Freshness is the same problem with the clock running the other way. The index is a copy, so it is wrong from the moment a document changes until the moment it is reindexed, and how wrong is a product decision somebody should make consciously. Drive it by change events where the source can emit them and fall back to a scheduled sweep where it cannot; key chunks by document id so an update replaces rather than duplicates; and handle deletions explicitly, because an answer quoting a policy that was withdrawn last month is worse than no answer at all — it is the Air Canada failure with extra machinery in front of it.

RAG, long context or fine-tuning

Context windows large enough to hold entire handbooks made the obvious question worth asking: why retrieve at all, when you can paste everything in? For a genuinely small and stable corpus — a product manual, a policy document, a single codebase file — pasting it in is the right answer, and building a retrieval pipeline for it is over-engineering. The reasons that break down are quantitative and they arrive quickly: cost scales with every token on every request, latency scales with the prompt, attention across a very long prompt is uneven, and no window holds a corporate wiki. Retrieval is what makes the input size independent of the corpus size.

Reach for RAG

  • The knowledge changes — daily prices, tickets, documents edited by people who do not deploy code.
  • Answers must cite a source, and a user has to be able to check the claim.
  • Different users may see different subsets of the same corpus.
  • The corpus is far larger than any prompt, and most of it is irrelevant to any one question.

Reach for fine-tuning

  • The problem is behaviour and format, not facts — a house style, a taxonomy, a rigid output shape.
  • The same instructions repeat on every call and dwarf the actual input.
  • You have thousands of labelled examples and a to prove it worked.
  • Volume is high enough that a shorter prompt pays back the training and the maintenance.

The two are not rivals and mature systems usually run both: a tuned model that knows the format and the tone, answering from passages retrieved at query time. What does not work is using to teach facts. Training on a document set does not create a lookup table — the facts blur into the weights, come back subtly altered, cannot be cited, and cannot be corrected without retraining. Every fact you might need to update, cite or restrict belongs in retrieval, and the three verbs in that sentence are the whole decision rule.

Five systems that retrieved exactly what they were told to

None of these were generation failures and four of them were not even retrieval failures in the technical sense — the systems found what the corpus and the permissions allowed them to find. What went wrong was upstream of the machinery, in decisions about what belonged in the corpus and who was allowed to reach it.

CaseWhat happenedThe control that was missing
Google AI Overviews, May 2024Search answers assembled from retrieved pages advised, among other things, adding non-toxic glue to pizza sauce — traceable to a joke post on a forum. Retrieval and grounding both worked; the source was a joke.Nothing ranked source authority. Grounding makes an answer traceable, not true — checklist 1.1 and 1.2.
NYC MyCity chatbot, March 2024A city business assistant answering from municipal material told business owners they could take a cut of workers’ tips and refuse tenants on the basis of income. It stayed online with a disclaimer added.No citation gate (5.3). An answer that cannot point at the line supporting it should not be shown at all.
Slack AI, August 2024A reported technique in which text placed in a public channel was retrieved by the assistant and used to draw content out of private channels the attacker was not in. Addressed after disclosure.The corpus contained attacker-writable content. If anyone can add to a source, the source is untrusted input.
Microsoft 365 Copilot, 2024Retrieval surfaced files users technically had permission to open but were never expected to find, at a scale that made years of loose permissions visible at once. Microsoft shipped a restricted search mode as a stopgap.The index inherited whatever the permissions actually were, rather than what anybody believed they were.
Air Canada, February 2024The opposite failure, and the reason this page exists: the chatbot invented a refund policy while the correct one sat on the airline’s own website. A tribunal ordered the airline to pay.No retrieval at all. The cheapest RAG system in this table would have prevented it.

Where it degrades

The honest limit of RAG is that it can only be as good as a search over a corpus somebody curated, and it inherits every problem that corpus has. It cannot tell a joke from a policy, an old draft from the approved version, or a document that is accurate from one that is accurate and confidential. Retrieval quality is a search problem and the remaining risk is an editorial one, which is why the items below are mostly organisational rather than technical.

  • Debugging the prompt when the right passage never reached it, which is most of the time.
  • Fixed-size chunking that cuts through tables, code and sentences and destroys the meaning it was indexing.
  • An index built once by hand, with no incremental update path and no story for deletions.
  • Access control applied to the results instead of the query, which leaks through scores, counts and timing.
  • A corpus anyone can write to, treated as trusted because it is internal.
  • Changing the embedding model without rebuilding the index, leaving two incomparable vector spaces in one store.
  • Vector-only retrieval on a corpus full of codes, identifiers and names that keyword search would find exactly.
  • No citations, so no user can verify an answer and no engineer can reproduce a complaint.
  • A demo corpus that became the production corpus because nobody re-decided what was in it.

When to use it

Use it when

  • Answering from a corpus that changes on its own schedule — documentation, policies, tickets, catalogues.
  • Anywhere the answer must be traceable to a source a user can open and check.
  • Corpora too large for any , where only a fraction is relevant to a given question.
  • Products where different users are entitled to different documents, and the boundary must be enforced per query.

Avoid it when

  • A corpus small and stable enough to paste into the prompt, where retrieval adds a pipeline and no accuracy.
  • Problems of style, tone or output format, which retrieval cannot touch — that is prompting or fine-tuning.
  • Questions needing aggregation over a whole dataset — counts, sums, trends — which a query against the database answers exactly.
  • Sources whose permissions you cannot represent per chunk, where a correct retrieval is itself the incident.

Sources and method

What this page stands on

  • 5 sources
  • 4 documented failures
  • Checked October 13, 2026

Researched with Claude. Finding and cross-checking the primary sources was done with Claude (Anthropic). Selection, writing and fact-checking: the Anatomy of IT Product editors.

Found this useful?

Share it with someone who is working on the same problem.