- RAG vs fine tuning comes down to which part of the system is wrong. RAG changes the input on each request, and fine tuning changes the weights before deployment.
- Try prompting and context first. Add RAG when the failure is missing or stale facts. Fine-tune only when an eval shows a behavior failure that survives both.
- Format errors usually need neither. Schema enforcement, such as OpenAI's Structured Outputs or vLLM's grammar backends, targets syntax with no training job.
- As of November 8, 2026, OpenAI has closed fine tuning to new organizations and ends new jobs for existing customers on January 6, 2027. Google, Amazon Bedrock, Together AI, and Fireworks AI still sell it.
- In this article's worked cost model, a cached prompt was cheapest at $1,375 a month on Gemini 3.5 Flash-Lite. A tuned model cost 5 percent more there and 76 percent more on OpenAI's
gpt-4.1-mini.
RAG vs fine tuning is a choice between two places to change an LLM system: the context a request carries and the weights that process it. Retrieval-augmented generation, introduced by Lewis et al. in 2020, adds retrieved passages to the input at request time. Fine tuning trains new weights from labeled examples before any request arrives. This article organizes the decision by failure mode, because the failure you observe tells you which part to change, and it prices each option with dated numbers.
#What RAG and fine tuning each change
RAG changes the context window on each request, and fine tuning changes the weights before deployment. That difference sets how fast a correction reaches users, what it costs per request, and what it can repair. Prompting sits in the same place as RAG, and constrained decoding acts after both.
Lewis et al. describe RAG as a generator paired with a retriever over a dense vector index, which they frame as parametric and non-parametric memory. Weights are the parametric part, and the index is the part you can edit without training. Fine tuning writes into the parametric part, so a change takes a job, an eval, and a deployment.
The LoRA fine tuning guide shows what that training job does to the weights on an open model. This article stays at the level of which failures justify running one.
#Try prompting and context first
Prompting and context come first in any RAG vs fine tuning decision. They cost no training, take effect on the next request, and set the baseline every other option must beat. Most teams should stay here until an eval proves otherwise.
Google's tuning guide says to consider tuning only when prompts do not produce the expected results consistently enough. OpenAI's fine-tuning guide says to set up evals first and to rethink the task or prompt if 50 examples have no impact. Do the prompt work with a test set beside you.
Work through these before you spend on anything else.
- Add the failing case as a few-shot example, and move stable instructions to the top of the prompt.
- Cut retrieved or pasted text that does not change the answer. The context engineering guide covers budgeting tokens across instructions, tools, and history.
- Put a schema on the output if the failure is structural.
- Turn on prompt caching so a long stable prefix stops being an argument for shortening it.
Stop when the cases in your eval still fail after you added an instruction and an example that cover them. Whatever fails at that point is your real target.
#Decision table by failure mode
To use this RAG vs fine tuning table, find the failure you observe in the left column and apply the first fix before you consider retrieval or training. The verdict names the option that addresses the cause, and rows marked "Cannot" are structural, so more budget will not change them.
| Failure you observe | Try first | RAG | Fine tuning | Verdict |
|---|---|---|---|---|
| Stale facts, such as last week's price | Paste the current value into context | Fixes it, swap the index | Cannot fix it without retraining | RAG |
| Facts the model never saw, such as internal docs | Add the document if it is short | Fixes it | Weak on rare facts | RAG |
| No citation or audit trail | None | Fixes it, retrieved chunks have IDs | Cannot, weights carry no source pointer | RAG |
| Per-user data access | Filter before the prompt is built | Fixes it, filter at retrieval | Cannot, weights are shared by all callers | RAG |
| Invalid JSON or schema violations | Structured outputs | No effect | Reduces the rate, no guarantee | Schema enforcement |
| Right schema, wrong field values | Few-shot examples | Helps when the value is in a document | Helps with consistent mappings | Prompt, then fine tuning |
| Tone or house style | System prompt and examples | No effect | Fixes consistent style | Fine tuning if prompts fail |
| Wrong tool selected | Fewer tools, better descriptions | Tool search retrieves from the catalog | Provider-suggested for large tool sets | Context, then tool search, then fine tuning |
| Malformed tool arguments | Strict schema mode | No effect | Helps with habits | Strict mode |
| Long prompt driving cost | Prompt caching | Adds tokens | Shortens the prompt, may raise the price | Caching, then recheck |
| Answer passage not retrieved | Improve chunking and search | The failing component | Cannot fix it | Fix retrieval |
| Passage retrieved, output ignores it | Reorder context, ask for quotes | Already present | Train with retrieved context | Combine |
#What RAG can and cannot fix
RAG fixes failures where the needed fact exists in a document you control and fails to reach the model. It cannot fix a retriever that misses the passage, an output that ignores a correct passage, or a style problem. Retrieved text changes what the model reads and leaves the weights alone.
The clearest evidence is Lewis et al.'s index hot-swap in Section 4.5. They built one index from a December 2016 Wikipedia dump, kept another from December 2018, and asked about 82 world leaders who had changed. RAG answered 70 percent correctly with the 2016 index on 2016 leaders and 68 percent with the 2018 index on 2018 leaders.
Mismatched indices scored 12 percent and 4 percent. The paper notes that parametric-only models need further training to pick up the same change.
Rare facts tell the same story. Soudani et al. tested twelve language models. They report that RAG beat fine tuning by a large margin on the least popular knowledge, while fine tuning still helped across popularity levels.
Berglund et al. report a related limit. GPT-3 and Llama-1 models fine-tuned on "A is B" statements could not answer the reversed question. The authors note that the reverse works when the statement sits in the context window.
Citations and permissions follow directly from where the data lives. A retrieved chunk has a document ID you can show and check, and a retrieval filter can apply per-user access rules. Weights have neither, and every caller shares them.
When the right passage never arrives, the fix is in retrieval. Check chunking, then hybrid search and reranking, and see the vector database guide for index choices. Measure with an eval that separates retrieval hits from answer quality, as the LLM evaluation guide describes.
#What fine tuning can and cannot fix
Fine tuning fixes behavior that stays consistent across requests, such as output structure, tone, classification boundaries, and tool-calling habits. It cannot deliver facts that change after training, cite a source, or enforce per-user access. Google's tuning page lists classification, summarization, extractive question answering, and chat among its use cases.
OpenAI's optimization guide adds nuanced translation and correcting instruction-following failures. Its preference-optimization guide targets chat messages with the right tone and style. Those are behaviors, and every one of them can be demonstrated with examples.
Format errors have a cheaper fix. OpenAI says Structured Outputs make responses follow your JSON Schema, with refusals as the exception. On open models, vLLM's structured outputs use xgrammar or guidance as constrained decoding backends.
Do not stack both by default. Google warns that applying controlled generation to tuned Gemini models can decrease quality because of a mismatch between tuning and inference.
Tool-call accuracy has more than one layer. OpenAI's function-calling guide advises fewer than 20 functions at the start of a turn and recommends strict mode. It suggests fine tuning for large function sets or difficult tasks.
Anthropic says Claude's tool selection degrades past 30 to 50 tools, a vendor figure with no independent measurement cited, and offers tool search as a fix.
Tool search is RAG over your tool catalog. Try it before fine tuning on any agent with a large tool-calling surface. The guides on AI agents and MCP servers cover the tool design around it.
A tuned model also inherits its base model's lifespan. OpenAI's deprecations page says fine-tuned versions follow the same shutdown schedule as their base, and gpt-4.1-mini is scheduled to shut down on January 14, 2027.
Amazon Bedrock's lifecycle policy blocks new fine-tuning jobs once a model enters Legacy, and Google excludes supervised fine tuning from its SLOs. Weights you host on an open base do not expire on a vendor's schedule.
#Who still offers fine tuning
Google's Agent Platform, Amazon Bedrock, Together AI, and Fireworks AI still sell fine tuning as of November 8, 2026. OpenAI is winding its platform down, Mistral has deprecated its fine-tuning feature, and Google's Gemini API has no tunable model. Check availability before you plan a RAG vs fine tuning decision around it.
| Provider | Status on November 8, 2026 | What you can tune | Training price | Tuned inference |
|---|---|---|---|---|
| OpenAI | Closed to new organizations. Existing customers until January 6, 2027 | gpt-4.1 and gpt-4.1-mini snapshots | $5.00 per 1M tokens on gpt-4.1-mini | $0.80 input, $3.20 output per 1M tokens, 2 times base |
| Google Agent Platform | Available | Gemini 3.5 Flash-Lite, 3.5 Flash, 3.1 Flash-Lite, 2.5 Pro, 2.5 Flash-Lite, 2.5 Flash | $3.00 per 1M tokens on 3.5 Flash-Lite | Base price in global region, 1.5 times in non-global regions for Gemini 3 and later |
| Gemini API and AI Studio | No tunable model | None | None | None |
| Amazon Bedrock | Available | Nova, Titan, Llama, and Claude 3 Haiku per its table | Per token, plus monthly storage | Not compared here |
| Mistral | Deprecated, no longer actively supported | Not stated | $4 minimum per job, $2 monthly storage per model | Not stated |
| Anthropic | No fine-tuning rate on its pricing page | Bedrock's table lists Claude 3 Haiku | None listed | None listed |
| Together AI | Available | Open models, LoRA by default | From $0.34 per 1M tokens, job minimums from $4 | Dedicated endpoints billed per minute |
| Fireworks AI | Available | Open models | $0.50 per 1M tokens LoRA SFT, up to 16B | Deployment billed per GPU-second |
Sources for the table are OpenAI and its pricing page, Google's pricing page, AI Studio, Bedrock customization and its model table, Mistral, Anthropic, Together's pricing and fine-tuning docs, and Fireworks. The platforms directory tracks hosts beyond these.
#RAG vs fine tuning costs, worked in code
In this model, fine tuning does not win on token cost once prompt caching is in the comparison, and training is the smallest line. The script below prices one workload five ways at rates fetched on November 8, 2026. Token counts are assumptions for illustration, so change them to your traffic before you trust the result.
Prices come from Google's Agent Platform pricing page, whose documentation still sits under Vertex AI URLs, and OpenAI's pricing page. OpenAI's column is useful only if you already have access, and Gemini Embedding 2 is priced as a preview.
REQUESTS = 1_000_000 # per month
PREFIX = 5_000 # instructions, tool definitions, few-shot examples
TUNED_PREFIX = 1_200 # the examples moved into the weights
USER = 300
RETRIEVED = 3_000 # six 500-token chunks
OUTPUT = 400
HIT = 0.9 # assumed share of a long stable prefix served from cache
# USD per 1M tokens, as of November 8, 2026.
VERTEX = dict(input=0.30, cached=0.03, output=2.50, embed=0.20, train=3.00)
OPENAI = dict(input=0.40, cached=0.10, output=1.60, embed=0.02, train=5.00)
VERTEX_TUNED_GLOBAL = dict(input=0.30, cached=0.03, output=2.50)
VERTEX_TUNED_REGIONAL = dict(input=0.33 * 1.5, cached=0.033 * 1.5, output=2.75 * 1.5)
OPENAI_TUNED = dict(input=0.80, cached=0.20, output=3.20)
def monthly(price, prefix, hit=0.0, retrieved=0, embed=None):
cached = prefix * hit
fresh = prefix - cached + USER + retrieved
embedding = USER * embed if embed else 0
parts = {
"cached_in": cached * price["cached"],
"fresh_in": fresh * price["input"] + embedding,
"output": OUTPUT * price["output"],
}
return {k: v * REQUESTS / 1e6 for k, v in parts.items()}
def report(name, base, tuned):
embed = base["embed"]
rows = [
("prompt, no cache", monthly(base, PREFIX)),
("prompt + cache", monthly(base, PREFIX, HIT)),
("RAG + cache", monthly(base, PREFIX, HIT, RETRIEVED, embed)),
("tuned", monthly(tuned, TUNED_PREFIX)),
("tuned + RAG", monthly(tuned, TUNED_PREFIX, 0.0, RETRIEVED, embed)),
]
print(name)
for label, parts in rows:
total = sum(parts.values())
detail = " ".join(f"{k} {v:8,.0f}" for k, v in parts.items())
print(f" {label:18s} ${total:>8,.0f} {detail}")
# Prefix length at which tuning matches prompt + cache.
tuned_cost = TUNED_PREFIX * tuned["input"] + USER * tuned["input"] + OUTPUT * tuned["output"]
per_prefix_token = HIT * base["cached"] + (1 - HIT) * base["input"]
fixed = USER * base["input"] + OUTPUT * base["output"]
print(f" break-even prefix: {(tuned_cost - fixed) / per_prefix_token:,.0f} tokens")
report("Vertex global, Gemini 3.5 Flash-Lite", VERTEX, VERTEX_TUNED_GLOBAL)
report("Vertex non-global tuned endpoint (1.5x)", VERTEX | dict(input=0.33, cached=0.033, output=2.75), VERTEX_TUNED_REGIONAL)
report("OpenAI gpt-4.1-mini", OPENAI, OPENAI_TUNED)
# One-off costs.
examples, tokens_each, epochs = 2_000, 1_900, 3
train_tokens = examples * tokens_each * epochs
print(f"training tokens: {train_tokens:,}")
for name, rate in [("Vertex 3.5 Flash-Lite", 3.00), ("OpenAI gpt-4.1-mini", 5.00), ("Fireworks LoRA SFT, up to 16B", 0.50)]:
print(f" {name:32s} ${train_tokens * rate / 1e6:,.2f}")
corpus = 200_000 * 500
print(f"corpus embedding, {corpus:,} tokens: OpenAI ${corpus * 0.02 / 1e6:,.2f}, Gemini Embedding 2 ${corpus * 0.20 / 1e6:,.2f}")
print(f"dedicated H100 for a month: ${8.00 * 730:,.0f}")
# If OpenAI's tuned prefix did hit the cache.
alt = monthly(OPENAI_TUNED, TUNED_PREFIX, HIT)
print(f"OpenAI tuned with cached prefix: ${sum(alt.values()):,.0f}")Vertex global, Gemini 3.5 Flash-Lite
prompt, no cache $ 2,590 cached_in 0 fresh_in 1,590 output 1,000
prompt + cache $ 1,375 cached_in 135 fresh_in 240 output 1,000
RAG + cache $ 2,335 cached_in 135 fresh_in 1,200 output 1,000
tuned $ 1,450 cached_in 0 fresh_in 450 output 1,000
tuned + RAG $ 2,410 cached_in 0 fresh_in 1,410 output 1,000
break-even prefix: 6,316 tokens
Vertex non-global tuned endpoint (1.5x)
prompt, no cache $ 2,849 cached_in 0 fresh_in 1,749 output 1,100
prompt + cache $ 1,512 cached_in 148 fresh_in 264 output 1,100
RAG + cache $ 2,562 cached_in 148 fresh_in 1,314 output 1,100
tuned $ 2,392 cached_in 0 fresh_in 742 output 1,650
tuned + RAG $ 3,938 cached_in 0 fresh_in 2,288 output 1,650
break-even prefix: 19,035 tokens
OpenAI gpt-4.1-mini
prompt, no cache $ 2,760 cached_in 0 fresh_in 2,120 output 640
prompt + cache $ 1,410 cached_in 450 fresh_in 320 output 640
RAG + cache $ 2,616 cached_in 450 fresh_in 1,526 output 640
tuned $ 2,480 cached_in 0 fresh_in 1,200 output 1,280
tuned + RAG $ 4,886 cached_in 0 fresh_in 3,606 output 1,280
break-even prefix: 13,231 tokens
training tokens: 11,400,000
Vertex 3.5 Flash-Lite $34.20
OpenAI gpt-4.1-mini $57.00
Fireworks LoRA SFT, up to 16B $5.70
corpus embedding, 100,000,000 tokens: OpenAI $2.00, Gemini Embedding 2 $20.00
dedicated H100 for a month: $5,840
OpenAI tuned with cached prefix: $1,832| Option, USD per month | Gemini 3.5 Flash-Lite, global | Gemini, non-global | OpenAI gpt-4.1-mini |
|---|---|---|---|
| Prompt, no cache | $2,590 | $2,849 | $2,760 |
| Prompt + cache | $1,375 | $1,512 | $1,410 |
| RAG + cache | $2,335 | $2,562 | $2,616 |
| Tuned | $1,450 | $2,392 | $2,480 |
| Tuned + RAG | $2,410 | $3,938 | $4,886 |
| Break-even stable prefix, tokens | 6,316 | 19,035 | 13,231 |
The break-even row is the prefix length at which a tuned model matches a cached prompt. Below 6,316 tokens on Gemini's global endpoint, caching the long prompt costs less than tuning it away. That number climbs to 13,231 tokens on OpenAI, where tuned tokens cost twice as much.
The tuned prefix stays uncached in this model. Google documents a 4,096-token caching minimum for most Gemini 3 models, and OpenAI's minimum varies by request settings before GPT-5.6. If OpenAI's tuned prefix did hit the cache, the tuned row would fall to $1,832, still above the cached prompt.
Training is a rounding error at this scale. 2,000 examples at 1,900 tokens for three epochs is 11.4M training tokens. That costs $34.20 on Gemini 3.5 Flash-Lite, $57.00 on OpenAI, and $5.70 for LoRA on Fireworks under 16B.
Embedding a 100M-token corpus once costs $2 on OpenAI or $20 on Gemini Embedding 2. A dedicated GPU changes the shape of the bill. One on-demand H100 on Fireworks at $8.00 per GPU-hour is $5,840 for a 730-hour month, before redundancy.
The script leaves out vector store hosting, reranking, ingestion, labeling, and eval time. Add those from your own quotes, and compare token prices with the Claude API pricing and Gemini API pricing guides.
#When to combine RAG and fine tuning
Combine them when facts change and a behavior failure also survives a good prompt, or when retrieval finds the right passage and the output still ignores it. Train on the retrieved context you serve in production, because a model trained on clean question-answer pairs never saw the distractors your retriever returns.
Zhang et al.'s RAFT makes that explicit. Training examples mix relevant documents with distractors that do not contain the answer, and the target output is a reasoning chain that cites the source passage.
The authors report that RAFT on LLaMA2-7B scored 74.00 on HuggingFace API questions, against 26.43 for the same model with plain RAG and 29.08 for GPT-3.5 with RAG. On HotPot QA, GPT-3.5 with RAG scored 41.5 and RAFT scored 35.28, so the gain is not universal.
Use these criteria before committing to both.
- A fact-shaped bucket and a behavior-shaped bucket both remain in your eval after prompt work.
- The retriever hits the right passage on most failing cases, so the output is the failing part.
- One task carries enough volume that its stable prefix is past the break-even length above.
Remember the premium. On OpenAI's rates, tuned plus RAG cost $4,886 against $2,616 for RAG alone, because every retrieved token is billed at the tuned rate. On Gemini's global endpoint the same pair cost $2,410 against $2,335.
#Settle RAG vs fine tuning with a failure audit
Settle RAG vs fine tuning by counting real failures, because the largest failure bucket names the cheapest fix. Spend a day on this before you build a pipeline or a training set. The steps below need only your logs and a spreadsheet.
- Pull 100 recent failures from logs or a golden dataset.
- Label each one with a row from the decision table. If it fits none, write a new row.
- Fix the largest bucket with the first-try column, and rerun the eval.
- Repeat until the remaining buckets resist prompting and context.
- Route fact-shaped survivors to RAG. See RAG topics for the retrieval side.
- Route behavior-shaped survivors to fine tuning, starting with 50 examples, and compare against your best cached prompt on accuracy and monthly cost. The LLM as a judge guide covers open-ended scoring.
If half your failures are stale or missing facts, stop and build retrieval. If what survives is a small bucket of format or style failures, start with a LoRA adapter on an open model. Choose a host that will not retire your base before the adapter pays off.
#Questions
Is RAG better than fine tuning?
RAG is better for facts and fine tuning is better for consistent behavior, so neither wins in general. Use RAG when answers depend on documents that change or that you must cite. Use fine tuning when evals show a format, style, or classification failure that survives a good prompt. Most teams should try prompting and context before either one.
Can you combine RAG and fine tuning?
Yes, and the useful version trains on retrieved context. Training on clean question-answer pairs and adding retrieval only at serving time mismatches what the model sees in production. Zhang et al.'s RAFT trains on documents that include distractors and on answers that cite the relevant passage. Expect to pay any tuned-model price premium on every retrieved token.
Does fine tuning reduce hallucinations?
Fine tuning can correct instruction-following failures, but it does not give a model access to facts it lacks. Soudani et al. found that RAG beat fine tuning by a large margin on the least popular facts. If a hallucination comes from missing knowledge, retrieval is the direct fix, and you still need to evaluate whether answers stay faithful to the retrieved text.
Is fine tuning cheaper than RAG?
Training is cheap, and tuned inference is where the cost sits. In this article's example at 1M requests a month, training cost $34 to $57 once, a tuned model cost $1,450 to $2,480 a month, and RAG with a cached prefix cost $2,335 to $2,616. The two options solve different problems, so compare them only when either one would fix the failure.
Can you still fine-tune GPT models with OpenAI?
Only if your organization already used the platform. As of November 8, 2026, OpenAI has closed fine tuning to new organizations, and eligible existing customers can create jobs until January 6, 2027, unless the base model shuts down earlier. Inference on fine-tuned models continues until the base model is retired, and gpt-4.1-mini is scheduled to shut down on January 14, 2027.
When should you fine-tune an LLM instead of changing the prompt?
Fine-tune when an eval shows a behavior failure that persists after you have added instructions, examples, and a schema, and you have labeled data. Google's tuning guide says to consider tuning when prompts do not produce the expected results consistently enough. OpenAI's guide says to set up evals first and to rethink the task if 50 examples have no impact.
How do you fine-tune an LLM?
Collect labeled examples in your provider's JSONL format, hold out a test set, train, and compare the tuned model with the base model and your best prompt. On open models, LoRA through Hugging Face PEFT is a common low-cost path, and the LoRA guide on this site includes a script that was executed with real output. On hosted models, check availability first.