RAG answer caching: Caching RAG Answers Safely

Day 77: Caching RAG Answers Safely
15 views
This guide focuses on RAG answer caching for production systems, with practical trade-offs for reliability, security, and cost. Caching RAG answers is a sharp knife. Done right, identical internal questions stop burning tokens. Done wrong, Tenant A sees Tenant B’s answer, or yesterday’s wrong runbook ships forever after a git push.
⚡ TL;DR: Cache only normalized question + tenant + corpus version + model/prompt version. Short TTLs. Never cache across tenants. Invalidate on index refresh. Prefer caching retrieval sets over final prose when answers must cite live code.

RAG answer caching: production guidance

python
# ✅ Tenant-scoped, versioned cache key
import hashlib, json

def rag_cache_key(*, tenant_id: str, question: str, corpus_ver: str,
                  prompt_ver: str, model_id: str) -> str:
    norm = " ".join(question.lower().split())
    payload = {
        "t": tenant_id,
        "q": norm,
        "c": corpus_ver,   # git SHA or KB ingestion id
        "p": prompt_ver,
        "m": model_id,
    }
    raw = json.dumps(payload, sort_keys=True).encode()
    return "rag:" + hashlib.sha256(raw).hexdigest()
❌ Keying only on the question string. That is how you leak between customers and environments.

What to cache

Layer Cache? Notes
Embedding of query Yes Per embedding model version
Retrieval hit list Often Invalidate with corpus_ver
Final natural-language answer Sometimes Only for FAQ-like, cited answers
Tool side effects Never Not a cache problem
For coding assistants, prefer caching ranked chunk IDs and re-running generation with fresh system rules. Prose caches go stale when POLICY.md changes.

Invalidation that actually runs

Hook your indexer (Day 27) to bump corpus_ver and delete keys by prefix or generation tag:
python
# ✅ Generation-based invalidation
def bump_corpus(tenant_id: str) -> str:
    ver = new_version()  # monotonic or git SHA
    redis.set(f"corpus_ver:{tenant_id}", ver)
    # optional: redis.scan_iter(f"rag:{tenant_id}:*") and delete
    return ver

Failure modes

Cross-env cache hits (staging key reused in prod) are as bad as cross-tenant. Include env in the key. Clock-skewed TTLs across gateway replicas can resurrect deleted answers — prefer generation counters over wall-clock alone when corpus_ver is unchanged but policy prompts changed.

Closing checklist

  • [ ] Tenant id mandatory in every cache key
  • [ ] corpus_ver + prompt_ver + model_id in key
  • [ ] TTL ≤ your freshness SLO (often hours, not weeks)
  • [ ] Integration test: same question, two tenants → two entries
  • [ ] Never serve cached answer without citations still present in index

Series navigation

Day 76: p99 of Agents: Queueing, Not Just Model Latency · Day 78: Load Shedding When the Model Is Sick Last updated September 11, 2026 Related: Cost-Aware RAG Caches: Reuse Answers for Identical Code Questions; Citation-Required RAG Answers: Force Models to Quote File Paths; RAG Evaluation on Bedrock: Offline Suites Before You Trust Code Answers.

Watch: 100 Days of AI on YouTube

Short videos from CheatCoders, one AI engineering topic per day.

Open the playlist on YouTube · CheatCoders on YouTube

Deep-dive PDF

Get the expanded guide for this post — extra diagrams-style checklists, failure modes, and a production walkthrough. Free when you subscribe to CheatCoders.

Already subscribed? or open the subscribe page.


Discover more from CheatCoders

Subscribe to get the latest posts sent to your email.

Comments

No comments yet. Why don’t you start the discussion?

Leave a comment

No account needed. Name and email are optional.