AAI Agentic Handbook
Ranking & Generation

Semantic cache

Senior levelReviewed Oct 2026In 5 interview questionsIn 1 post

Reusing a stored answer when a new query's embedding is close enough to a past one. Saves cost and latency; risks returning the wrong answer.

In plain English

A normal cache only helps when the exact same request repeats. A semantic cache stores past questions as embeddings and, when a new question is very similar in meaning, returns the saved answer without calling the Large Language Model (LLM). It is fast and cheap, but 'similar' is not 'the same', so a careless threshold can hand someone an answer to a different question.

Analogy

A help-desk worker who recognises 'how do I reset my password?' and 'forgot my password, what now?' as the same question and reads the standard reply, but must notice when someone asks 'how do I stop password resets?'.

Common pitfall

Tuning the threshold for hit rate. Every point of hit rate bought by lowering the threshold is paid for in wrong answers served at full confidence.

How it actually works

Flow: embed the normalised query → Approximate nearest neighbour (ANN) lookup in a cache index scoped by tenant, locale, user permissions and prompt/model version → if top cosine ≥ threshold (commonly 0.92–0.97), return the stored answer; else generate, then store. The hard parts are correctness, not speed. Embeddings are weak on negation, numbers and entities ('cancel order 1182' vs 'cancel order 1183' score ~0.98), so production systems add guards: exact match on extracted entities, a cross-encoder or small-LLM equivalence check on hits, and exclusion of personalised or time-sensitive intents. Invalidate on corpus change (key by document-version hash), on prompt or model change, and with a TTL & cache invalidation. Do not confuse it with Prompt caching, which caches the KV state of an exact prefix at the provider and is always correct; prompt caching is the safer first win.

What I'd ship on day one

Provider prompt caching first. Semantic cache (Redis vector search, GPTCache, or a gateway feature) only for an allow-list of non-personalised intents; threshold 0.95; key scope = tenant + locale + prompt version + model + corpus version; TTL 24 h; entity-equality check on hits; 1% of hits regenerated and judged.

Worked example

Customer-support bot, 2M queries/month, ~35% are FAQ-style ('where is my invoice', 'change billing email'). Cache only intents tagged faq, threshold 0.95, plus a check that extracted entities (order ids, plan names) match. Hit rate 24% of total traffic; p50 latency on hits 40 ms vs 2.1 s; sampled precision of hits 99.2% by LLM judge. Personalised intents ('why was I charged twice') are never cached.

In the interview

Say: I start with provider prompt caching because it is always correct, then add a semantic cache only for non-personalised intents, with a high threshold, entity matching, and a sampled correctness audit on hits. Expect the follow-up: 'how do you measure false hits?' Sample 1% of hits, regenerate fresh, and have a judge compare; alert above 1% disagreement.

User
Gateway
Cache index
Checker
LLM
1
Where is my invoice?User → Gateway
2
ANN, tenant+localeGateway → Cache index
3
Hit, cosine 0.96Cache index → Gateway
4
Entities + intent match?Gateway → Checker
5
PassChecker → Gateway
6
Cached answer, 40 msGateway → User
7
(on miss) generateGateway → LLM
The checker step is what separates a cache from a wrong-answer generator

Numbers worth knowing

Threshold
0.92–0.97 cosinestart at 0.95; depends on embedding model
Realistic hit rate
10–30% of trafficsupport or FAQ-heavy workloads; < 5% for open-ended assistants
Hit latency
20–60 msembedding + ANN lookup + checker skipped on exact hash match

How to decide

WhenDo this
Answers depend on user, account state or timeDo not semantic-cache; use prompt caching only
High repeat FAQ traffic in a narrow domainSemantic cache on allow-listed intents with entity check
Corpus updates hourlyKey by corpus version or keep TTL ≤ 1 h

Cost maths

Savings = hit rate × queries × LLM cost per query − cache cost. 2M queries/month × 24% hits × $0.012 = $5,760/month saved. Cache cost: embeddings (2M × 20 tokens at $0.02/M ≈ $0.80), a small Redis node (~$200/month), checker calls on hits (480k × $0.0005 = $240). Net ≈ $5,300/month, provided false hits stay < 1%.

Operating it

Time to scale up when…
  • FAQ-style intents > 20% of traffic and stable: worth adding
  • Sampled false-hit rate > 1%: raise threshold or add a cross-encoder check
  • Cache index > 10M entries: add TTL eviction and per-tenant caps
What to monitor
  • Hit rate by intent; trend, alert on a sudden > 2× jump (threshold or embedding bug)
  • Sampled false-hit rate; alert > 1%
  • 'Didn't answer my question' feedback on cached vs fresh answers; alert if cached is > 1.5× fresh

When it goes wrong

What users saw

Users asking how to keep auto-renew on were told how to turn it off

How it was caught

Spike in 'didn't answer my question' feedback on a single intent; trace review showed cache hits

Root cause

'How do I turn off auto-renew' and 'how do I keep auto-renew on' embedded at cosine 0.95; the threshold was 0.93 and there was no checker

Fix

Threshold to 0.96, small-LLM equivalence check on every hit, negation-pair test cases added to the cache regression suite

Sources

  1. GPTCache: semantic cache for LLMs — Zilliz, 2023docs
  2. Prompt caching — Anthropic, 2025docs

Check yourself

Three questions. Every option is explained once you answer.

1ConceptWhy is provider prompt caching the safer first win than a semantic cache?
2ScenarioHigh-repeat support bot. 'Cancel order 1182' and 'cancel order 1183' embed at cosine 0.98. How do you keep a semantic cache safe?
3Calculation2M queries/month, 24% hit rate, $0.012 per LLM call; cache costs ~$440/month all-in. Net monthly saving?