---
term: 'RAG (Retrieval-Augmented Generation)'
seoTitle: 'RAG (Retrieval-Augmented Generation): Pipeline, ACLs, vs Fine-Tuning'
headline: 'What is RAG (Retrieval-Augmented Generation)?'
slug: retrieval-augmented-generation-rag
category: ai-modern-stack
shortDefinition: 'RAG is a technique that retrieves documents at query time and adds them to the prompt, so an LLM answers from data, not memory.'
relatedTerms:
  - vector-database-embeddings
  - api-key-security
  - cloud-code-serverless-functions
  - access-control-lists-acl
contrastsWith:
  - vector-database-embeddings
aboutTerms:
  - 'Retrieval-Augmented Generation'
  - 'Chunking'
  - 'Grounding'
faq:
  - question: 'What is RAG in simple terms?'
    answer: 'A technique where your app searches a knowledge base for relevant documents and pastes them into the LLM''s prompt, so the answer is grounded in real, current, or private data rather than the model''s frozen training memory. The open-book exam to a plain LLM''s closed-book one.'
  - question: 'Why use RAG?'
    answer: 'It fixes three LLM gaps at once, without retraining: hallucination (grounding answers in retrieved text), the training cutoff (fetching current data), and the model never having seen your private documents. And because the sources are known, the answer can cite them.'
  - question: 'How does RAG work?'
    answer: 'Two phases. Offline: load documents, split them into chunks, embed each chunk into a vector, store them in an index. Online: embed the user''s question, retrieve the most similar chunks, add them to the prompt, and let the model generate a grounded answer from that context.'
  - question: 'What is the difference between RAG and fine-tuning?'
    answer: 'They change different things. RAG injects knowledge — facts, freshness, private documents — at query time. Fine-tuning changes behavior — style, format, domain reasoning — baked in during training. Fine-tuning teaches how to respond; RAG supplies what to respond about; specialized assistants often use both.'
  - question: 'Do long context windows make RAG obsolete?'
    answer: 'No. Even with million-token windows, stuffing everything in costs far more per query and runs slower, and studies find accuracy degrading well before the window fills — "context rot." Freshness and access control still require retrieval. The 2026 default is hybrid: retrieve a relevant subset, then reason over it with a long-context model.'
  - question: 'What is chunking and why does it matter?'
    answer: 'Splitting documents into retrievable pieces — and retrieval quality depends heavily on it. Chunks too large dilute relevance and waste prompt budget; too small lose context. A common baseline is a few hundred tokens with overlap, though structure-aware splitting (by heading, paragraph, or code block) usually beats fixed sizes.'
  - question: 'Does RAG eliminate hallucinations?'
    answer: 'It reduces them; it does not eliminate them. The model can still misread retrieved context, blend stale and fresh passages, or answer confidently from bad retrievals. And most "RAG hallucinations" are retrieval failures in disguise — the wrong chunks were fetched, so the grounded answer is grounded in the wrong thing.'
  - question: 'How do you keep RAG from leaking documents a user shouldn''t see?'
    answer: 'Filter retrieval by permissions, not just similarity. Vector search ranks by meaning and knows nothing about who may read what, so store access-control metadata with each chunk and constrain the query to documents the asking user is allowed to see — before the top-k selection, not after.'
  - question: 'What is agentic RAG?'
    answer: 'Traditional RAG retrieves once and generates once. Agentic RAG puts a model in charge of retrieval — deciding when and what to fetch, breaking a question into sub-queries, iterating, and critiquing results before answering. The pipeline becomes a control loop; the trade is latency and unpredictability for harder questions handled well.'
  - question: 'When is RAG overkill?'
    answer: 'When the knowledge you need is public, stable, and already inside the model, plain prompting suffices. When your corpus is small and fits comfortably in the prompt, pasting it in — especially with prompt caching — beats standing up a retrieval pipeline. RAG earns its complexity on large, private, or changing knowledge.'
codeLanguages: [javascript, dart, swift, kotlin]
externalAuthorities:
  - name: 'Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks (Lewis et al., 2020)'
    url: 'https://arxiv.org/abs/2005.11401'
  - name: 'Retrieval-Augmented Generation for LLMs: A Survey (Gao et al.)'
    url: 'https://arxiv.org/abs/2312.10997'
  - name: 'RAGAS — evaluation metrics'
    url: 'https://docs.ragas.io/en/stable/concepts/metrics/available_metrics/'
  - name: 'Chunking strategies for RAG — Weaviate'
    url: 'https://weaviate.io/blog/chunking-strategies-for-rag'
cta:
  title: 'RAG is ordinary backend work'
  text: 'Store documents, index vectors beside your data, filter retrieval by ACL, and call the model from Cloud Code with the key server-side — Back4app supplies every piece except the prompt.'
  linkText: 'Start building free'
  linkUrl: 'https://www.back4app.com/signup'
author: 'Back4app Engineering'
publishedDate: '2026-07-30'
translationKey: retrieval-augmented-generation-rag
---

**RAG is a technique that retrieves documents at query time and adds them to the prompt, so an LLM answers from data, not memory.** Introduced by [Lewis et al. in 2020](https://arxiv.org/abs/2005.11401), it is the open-book exam to a plain model's closed-book one: instead of relying on what it memorized during training, the model consults material you supply and answers from it — grounded, current, private-aware, and, because the sources are known, *citable*. For a backend developer the reassuring truth under the hype is that RAG is not a framework you must adopt; it is a for-loop you can already build.

## Key takeaways

| Question | Answer |
| --- | --- |
| The move | Retrieve relevant chunks → add to prompt → generate a grounded answer |
| The three gaps it fixes | Hallucination · training cutoff · no access to your private data |
| vs. fine-tuning | RAG supplies *knowledge*; fine-tuning changes *behavior* — often both |
| The dominant error | Retrieval failure — wrong chunks in, confident wrong answer out |
| The production must | Filter retrieval by [permissions](/glossary/access-control-lists-acl/), not similarity alone |

## The two phases

```text
INGESTION (offline, once per document)
  load → chunk (split into ~hundreds of tokens, with overlap)
       → embed each chunk into a vector
       → store vector + text + ACL metadata in an index

QUERY (online, per question)
  embed the question → similarity search for top-k chunks (usually 5–10)
       → filter to what THIS user may read
       → augment the prompt with the chunks
       → LLM generates an answer grounded in them (+ citations)
```

The whole online phase, server-side, in one function:

**JavaScript:**

```javascript
// JavaScript — Cloud Code (cloud/main.js): RAG is a for-loop, not a framework
Parse.Cloud.define('askDocs', async (req) => {
  // 1 · embed the question (LLM API key stays server-side)
  const qVec = await embed(req.params.question);

  // 2 · retrieve — similarity search, ACL-FILTERED to this user's docs
  const chunks = await vectorSearch('DocChunk', qVec, {
    limit: 6,
    aclUser: req.user, // never retrieve what the asker can't read
  });

  // 3 · augment + generate
  const context = chunks.map((c) => c.get('text')).join('\n---\n');
  return await complete(`Answer using ONLY this context:\n${context}\n\nQ: ${req.params.question}`);
  // Answer cites the retrieved chunks — grounded, and permission-safe.
});
```

**Flutter:**

```dart
// Flutter / Dart — Back4app Flutter SDK
// The client just asks — retrieval, grounding, and ACLs happen server-side
final answer = await ParseCloudFunction('askDocs')
    .execute(parameters: {'question': 'What is our refund window?'});
print(answer.result); // grounded in the user's own documents, with citations
// No embeddings, no vector math, no LLM key on the device — RAG's backend
// is ordinary backend work: store docs, index vectors, query, call the model.
```

**Swift:**

```swift
// iOS / Swift — Back4app Swift SDK
// The client just asks — retrieval, grounding, and ACLs happen server-side
let answer: String = try await Cloud.run(
    name: "askDocs",
    parameters: ["question": "What is our refund window?"])
print(answer) // grounded in the user's own documents, with citations
// No embeddings, no vector math, no LLM key on the device — RAG's backend
// is ordinary backend work: store docs, index vectors, query, call the model.
```

**Kotlin:**

```kotlin
// Android / Kotlin — Back4app Android SDK
// The client just asks — retrieval, grounding, and ACLs happen server-side
val params = mapOf("question" to "What is our refund window?")
val answer = ParseCloud.callFunction<String>("askDocs", params)
println(answer) // grounded in the user's own documents, with citations
// No embeddings, no vector math, no LLM key on the device — RAG's backend
// is ordinary backend work: store docs, index vectors, query, call the model.
```

```mermaid
flowchart LR
  accTitle: RAG ingestion and query pipelines
  accDescr: In the ingestion phase, documents are loaded, split into chunks, embedded into vectors, and stored with access-control metadata in a vector index. In the query phase, the user question is embedded, similar chunks are retrieved and filtered by the user's permissions, the prompt is augmented with them, and the model generates a grounded answer with citations.
  subgraph Ingest["Ingestion — offline"]
    D["Documents"] --> CH["Chunk"] --> EM["Embed"] --> IDX[("Vector index<br/>+ ACL metadata")]
  end
  subgraph Query["Query — online"]
    Q["Question"] --> QE["Embed"] --> R["Retrieve top-k"]
    IDX --> R
    R --> F["Filter by user's ACL"] --> AUG["Augment prompt"] --> G["Generate<br/>grounded answer"]
  end
```

## Why RAG: the three gaps

A plain LLM has three structural weaknesses, and RAG addresses all of them without retraining. **Hallucination** — models answer confidently whether or not they know; grounding every claim in retrieved text gives the model something true to say. **The training cutoff** — a model's knowledge freezes at training time; retrieval fetches today's data. **Private data** — the model never saw your documents; retrieval is how it reads them at query time. The bonus that closed-book models can't offer: because the retrieved chunks are known, the answer can **cite its sources** like footnotes — the single biggest trust advantage RAG has.

## RAG vs. fine-tuning

| | RAG | Fine-tuning |
| --- | --- | --- |
| Changes | *Knowledge* — what the model knows | *Behavior* — how it responds |
| Update speed | Instant — add a document | Retrain to change |
| Freshness | Always current | Frozen at training |
| Citations | Yes — sources are known | No |
| Cost shape | Per-query retrieval + tokens | Upfront training |
| Best for | Facts, private docs, change | Style, format, domain reasoning |

They are not rivals: fine-tuning teaches the model *how* to respond, RAG supplies *what* to respond about, and a specialized domain assistant frequently uses both — a fine-tuned voice answering from a retrieved knowledge base.

## Is RAG dead? The long-context question, answered

The honest treatment the head-term pages avoid. Context windows now reach millions of tokens, prompting the recurring "just stuff everything in the prompt" argument. Three facts keep retrieval alive. **Cost and latency:** paying to process a giant context on *every* query is dramatically more expensive and slower than fetching the relevant slice — orders of magnitude, at scale. **Context rot:** studies through 2025 found model accuracy degrading well before the window fills — relevant facts buried in a huge context get missed, so a bigger window is not a reliably better answer. **Freshness and access control:** a static mega-prompt is stale the moment data changes and blind to who may read what. The 2026 consensus is not "RAG or long context" but *both* — retrieve a generous, relevant, permission-filtered subset, then reason over it with a long-context model. Pure long-context is fine only for small, stable, non-sensitive corpora.

## Retrieval is where RAG fails

The framing that reorganizes how you debug a RAG system: **garbage retrieved is confident garbage generated.** Most failures blamed on the model are retrieval failures wearing a generation costume — the wrong chunks were fetched, so a perfectly faithful answer grounds itself in the wrong material. This makes two variables the ones that actually move quality. **Chunking:** pieces too large dilute relevance and burn prompt budget; too small lose the context that made them meaningful — structure-aware splitting (by heading, paragraph, code block) usually beats fixed sizes ([the strategies matter](https://weaviate.io/blog/chunking-strategies-for-rag)). **Hybrid retrieval:** combine keyword search (exact terms, names, IDs) with vector search (meaning), then *re-rank* the merged candidates with a stronger relevance model before prompting — recall from both, precision from the re-ranker. And measure the two halves separately, in the [RAGAS](https://docs.ragas.io/en/stable/concepts/metrics/available_metrics/) vocabulary: retrieval metrics (did we fetch the right chunks?) versus faithfulness (is every claim supported by what we fetched?) — because they fail independently and fix differently.

## The security gap nobody mentions

Vector similarity ranks by meaning and knows *nothing* about permissions — which makes naive RAG a data-leak engine. Embed a company's documents into one index without access metadata, and any user's question can retrieve any document, because the finance report and the intern's question are just nearby points in vector space. Post-retrieval filtering is not the fix either: drop forbidden chunks after the top-k selection and you both leak their existence and break the top-k contract (you asked for six and got two). The correct pattern: **store [ACL](/glossary/access-control-lists-acl/) metadata with each chunk and constrain retrieval to the asking user's permitted set *before* similarity ranking** — permission-filtered retrieval, not permission-filtered display. The code tabs' `aclUser` parameter is exactly this, and it is the difference between a demo and a system you can ship.

## Common use cases

- **Support and knowledge chat** — answer from a company's actual docs, with citations, current as of the last ingest.
- **Search over private corpora** — legal, medical, internal wikis: meaning-based retrieval the keyword box never gave you.
- **Customer-scoped assistants** — each user's own data, ACL-filtered so retrieval never crosses a tenant boundary.
- **Grounded analytics** — questions answered from live records rather than a model's stale guess.
- **Documentation and onboarding** — a model that quotes the manual instead of improvising it.

## Do you even need RAG? A decision matrix

| Situation | Reach for |
| --- | --- |
| Knowledge is public, stable, in the model | Plain prompting — no pipeline |
| Corpus fits in the prompt, rarely changes | Paste it in (with prompt caching) |
| Large, private, or changing knowledge | RAG — its home |
| Need the model to *behave* differently | Fine-tuning (maybe plus RAG) |
| Answers must cite sources | RAG — citations come free |
| Multi-user data with permissions | RAG with ACL-filtered retrieval — mandatory |

## Limitations and trade-offs

- **RAG reduces hallucination; it doesn't remove it.** Faithfulness must be measured, not assumed — the model can still misread good context.
- **Quality lives in retrieval.** Most of the engineering effort — chunking, hybrid search, re-ranking — is upstream of the model, where the wins are.
- **Embeddings have a version.** Change the embedding model and every stored vector must be regenerated; re-embedding a large corpus is a real migration.
- **It adds moving parts.** Ingestion pipelines, an index to maintain, extra per-query tokens and latency — real cost that a small stable corpus may not justify.
- **Permissions don't come for free.** ACL-filtered retrieval is the load-bearing security work, and it's the part demos skip and incidents rediscover.

## RAG on Back4app

Back4app is an open-source Backend-as-a-Service (BaaS) platform that combines a managed database, auto-generated REST and GraphQL APIs, authentication, file storage, and Cloud Code serverless functions. The "RAG is a for-loop" claim is literal here: documents are ordinary objects with [file storage](/glossary/api) for the originals; chunk vectors live as array fields beside them, [indexed](/glossary/database-index) for [similarity search](/glossary/vector-database-embeddings); the [ACLs](/glossary/access-control-lists-acl/) that already govern every query become the permission filter on retrieval *for free* — the same rule that stops a user reading another's records stops the retriever fetching them; and the orchestration — embed, retrieve, augment, generate — is a [Cloud Code function](/glossary/cloud-code-serverless-functions/) calling the model's [API with the key held server-side](/glossary/api-key-security/), exactly as the code tabs show. No framework, no separate vector service to secure, no LLM key on the device — RAG stops being an AI project and becomes backend engineering you already know how to do.
