Cookbook: Caching & Invalidation
On this page
Practical patterns for working with RetrievalCache in a production RAGSystem.
Recipe: Tune cache size and TTL for your traffic pattern
from zerda.rag.core import RAGConfig
config = RAGConfig(
enable_retrieval_cache=True,
cache_maxsize=2000, # higher for high-cardinality query traffic
cache_ttl=900, # 15 minutes — balance freshness vs. hit rate
)
Set cache_ttl=0 (or any value <= 0) to disable time-based expiry entirely — RAGSystem translates this to ttl=None internally.
Recipe: Monitor hit rate in production
stats = rag.get_cache_stats()
if stats and stats["hit_rate"] < 0.2:
logger.warning("Low cache hit rate (%.1f%%) — consider raising cache_ttl "
"or investigating query diversity.", stats["hit_rate"] * 100)
Recipe: Invalidate on external content updates
If a document is modified by a process other than RAGSystem.add_documents() / .remove_document() — for example, a direct write to the vector DB — the retrieval cache won't know about it automatically:
rag.invalidate_cache() # clears everything; simplest, safest option
add_documents() and — indirectly, via remove_document()'s stats update — already keep the cache roughly consistent for changes made through RAGSystem's own API; invalidate_cache() exists for everything else.
Recipe: Avoid cache-clearing storms during bulk ingestion
Every successful call to add_documents() clears the entire retrieval cache (see RAGSystem.add_documents side effects). If you're ingesting documents one at a time in a loop, you're also fully invalidating the cache on every iteration:
# Bad: clears the cache N times
for doc in documents:
rag.add_documents([doc])
# Better: batch, so the cache is only cleared once
rag.add_documents(documents)
Recipe: Skip caching for one-off diagnostic queries
The retrieval cache has no per-call opt-out — it's controlled only via RAGConfig.enable_retrieval_cache at construction time. For a one-off query you don't want cached (e.g. an internal health check), call vector_db.search() directly instead of going through rag.retrieve():
raw_results = rag.vector_db.search("health check probe", top_k=1, score_threshold=0.0)
Recipe: Cold-start warming
Since retrieve()'s cache lookup happens before query expansion and reranking, "warming" the cache for known-frequent queries just means calling retrieve() for them once at startup:
COMMON_QUERIES = ["how do I reset my password", "what is the refund policy"]
for q in COMMON_QUERIES:
rag.retrieve(q)
See also: RetrievalCache API reference for the full method list and internal eviction/expiry behavior.