RAG architecture from scratch: components and data flow
Strip away the framework names and RAG is a simple loop: turn documents into searchable units, find the units relevant to a question, put them in a prompt, and generate an answer. Everything else is engineering around failure modes.
Two pipelines, not one
Offline (ingestion): parse → clean → chunk → embed → index.
Online (query): rewrite → retrieve → filter → rerank → assemble context → generate → verify.
Conflating them is a common design error. Ingestion is batch, idempotent, and cheap to retry. Query is latency-sensitive and must degrade gracefully.
Components
| Layer | Responsibility | Typical failure |
|---|---|---|
| Parser | Extract text and structure | Lost tables, broken reading order |
| Chunker | Create retrieval units | Splits clauses from context |
| Embedder | Map text to vectors | Weak on identifiers and jargon |
| Index | Store and search vectors | Stale data, no metadata filters |
| Retriever | Return candidates | Low recall at the chosen k |
| Reranker | Reorder candidates | Too slow, or never added |
| Assembler | Build the context | Redundancy, wrong ordering |
| Generator | Write the answer | Unsupported claims |
| Verifier | Check claims against evidence | Missing entirely |
| Evaluator | Measure all of the above | Never built |
A minimal data model
{
"chunk_id": "doc-42::s3.1::c2",
"doc_id": "doc-42",
"text": "...",
"metadata": {
"title": "Master Services Agreement",
"section": "3.1",
"page": 7,
"type": "msa",
"effective": "2024-01-01",
"acl": ["legal-team"]
},
"embedding": [0.0123, -0.0441, ...]
}
The acl field matters: retrieval must filter by what the user is allowed to
see before ranking. Post-filtering leaks information through scores and counts.
The query path
- Normalize the question. Resolve pronouns from conversation history.
- Classify intent. Is this answerable from documents at all?
- Rewrite for retrieval. Expand acronyms, add domain synonyms.
- Retrieve broadly. Hybrid search, k = 30–50.
- Filter. Metadata and permissions.
- Rerank. Cross-encoder down to 5–8.
- Assemble. Deduplicate, order strongest-first, label sources.
- Generate. Grounded prompt with explicit refusal instruction.
- Verify. Check claims against the exact passages.
- Log. Store everything for audit and evaluation.
What to build first
Resist the urge to start with generation. Build in this order:
- Parser and chunker with metadata
- A 25-question golden set
- BM25 baseline + recall@k
- Dense retrieval + comparison
- Hybrid + reranking
- Generation with citations
- Verification and refusal
- Latency and cost optimization
Each step has a measurable acceptance criterion. If you can't measure it, don't build it yet.
Latency budget
For an interactive system, aim for:
- Query rewrite: < 150 ms (or skip)
- Retrieval: < 200 ms
- Rerank: < 300 ms
- Generation: 1–4 s (streamed)
- Verification: 0.3–1 s (or async)
Verification can run asynchronously for low-risk use cases, but must block for regulated ones.
Architecture test: can you explain, for a single bad answer, which layer failed and why? If not, you don't have observability — you have a black box.
Designing your first production RAG system?
I can review your architecture and tell you which layer will fail first — before you build it.
Book a 20-minute diagnostic