How to Implement Semantic Caching for LLM APIs in Enterprise Production
Semantic caching cuts LLM API costs 30–50% by returning cached responses to similar queries. Learn the architecture, threshold tuning, and multi-tenant isolation.
Semantic caching for LLM APIs is the caching layer that intercepts incoming prompts before they reach the model, embeds them into vectors, and returns a previously computed response when the new prompt is close enough in meaning to one already answered. It is not the same as prompt caching — which is a server-side provider feature that reuses KV-attention states for repeated system-prompt prefixes — and understanding that distinction is the first prerequisite for designing the right caching strategy for your stack. Semantic caching operates client-side, at the gateway or application layer, and can eliminate 30–50% of LLM API calls entirely on query-repetitive workloads.
The economics are decisive. A frontier model inference call costs 300–500ms at p50 and anywhere from $0.003 to $0.06 per 1,000 input tokens depending on the model tier. A semantic cache hit costs 2–5ms and a fraction of a cent for the embedding lookup. On enterprise workloads where thousands of users ask variations of the same questions — customer support, internal knowledge bases, developer documentation, sub-question answering inside agentic pipelines — the hit rate on a well-tuned semantic cache runs 30–50%. That is 30–50% of your inference budget disappearing from the bill without degrading answer quality.
This guide is written for engineers deploying LLM APIs at enterprise scale — teams that have moved past the prototype stage and are now optimizing for production cost, latency, and reliability. It covers the two-layer cache architecture, how to tune similarity thresholds without causing data quality regressions, multi-tenant isolation requirements, embedding model selection, and the observability instrumentation that tells you whether your cache is actually helping.
What Is Semantic Caching for LLMs?
Standard caching is deterministic: hash the input, check for an exact key match, return the stored value if found. That works for repeated identical requests but misses the vast majority of semantically equivalent queries — a user asking 'How do I reset my password?' and another asking 'What are the steps to recover my account password?' will hash to completely different keys despite requiring the same answer. Semantic caching replaces the exact-hash lookup with a vector similarity search: the incoming prompt is embedded, the resulting vector is compared against stored prompt vectors in a vector index, and the response is served from cache when the similarity score exceeds a configurable threshold.
- →Embedding: the incoming prompt is converted to a dense vector using a fast embedding model — typically 5–50ms depending on whether you use a local model or a managed API. This embedding cost is the constant overhead of every cache lookup, whether it hits or misses.
- →Similarity search: the prompt vector is queried against the cache's vector index using approximate nearest-neighbor (ANN) search. Tools like Qdrant, Redis Vector Search, and Weaviate all support this. The query returns the k nearest stored vectors and their similarity scores in single-digit milliseconds for caches up to tens of millions of entries.
- →Threshold decision: if the top match exceeds the configured cosine similarity threshold (typically 0.85–0.95), the stored response is returned immediately. Below the threshold, the request passes through to the LLM and — after the LLM responds — the new prompt-response pair is stored in the cache for future lookups.
- →Cache population: the write path stores both the embedded prompt vector (as the cache key) and the full LLM response (as the cache value). The stored prompt is the canonical phrasing; all semantically similar future prompts will map to this entry.
Semantic Caching vs. Prompt Caching: When to Use Which
These two techniques are complementary, not competing, but they operate at different layers and solve different problems. Prompt caching is a server-side optimization offered by providers like Anthropic and OpenAI: when the same system-prompt prefix is sent repeatedly, the provider caches the KV-attention state and charges a reduced rate (typically 10–20% of standard input token cost) on cache hits. It reduces cost per call for applications with long, repeated system prompts — but it does not eliminate the API call itself, and it does not help with query-side variation.
- →Prompt caching (server-side): reduces cost per call on repeated system-prompt prefixes. Works on any workload. No additional infrastructure. No risk of cross-user response sharing. Recommended as a baseline optimization for all LLM applications with system prompts longer than ~500 tokens.
- →Semantic caching (client-side): eliminates entire API calls for semantically similar queries. Requires a vector index, an embedding step, and careful threshold tuning. Best suited for query-repetitive workloads where users ask similar questions frequently. Requires tenant isolation in multi-user deployments.
- →Using both together: a production LLM serving layer should run prompt caching at the provider level (automatic, minimal code change) and add semantic caching at the gateway level for workloads with high query repetition. The two techniques target different cost drivers and compound without conflict.
- →When semantic caching alone is not enough: for agentic pipelines where every query is unique and context-dependent, semantic cache hit rates may be under 5%, making the embedding overhead a net negative. Measure your query distribution before investing in semantic caching infrastructure.
The Two-Layer Cache Architecture
Every production semantic cache implementation converges on a two-layer design. Layer 1 is exact-match; Layer 2 is semantic. Structuring it this way ensures that truly identical requests are served at O(1) speed without embedding overhead, while semantic matching is reserved for the cases that warrant it. This pattern integrates naturally with an LLM gateway that sits in front of your model endpoints, centralizing cache logic, cost attribution, and routing in one place.
- →Layer 1 — exact-match KV store: hash the scoped cache key (system_prompt + user_query + model_name + temperature_bin). Look up in Redis or DynamoDB. On a hit, return immediately — no embedding, no vector search, sub-millisecond response. This layer handles re-submissions of identical queries, polling patterns, and retries without paying embedding cost.
- →Layer 2 — semantic vector index: on a Layer 1 miss, embed the incoming prompt and run a similarity search against the vector index. On a hit above threshold, retrieve the cached response from the backing store. On a miss, route to the LLM.
- →Write path: after the LLM returns a response, write both layers. Store the exact hash in Layer 1 with a TTL. Store the embedded prompt vector in Layer 2 with the response pointer. If the prompt produces non-deterministic, user-specific, or time-sensitive output, skip the write path entirely — not all responses should be cached.
- →Cache scope: include the model name and temperature setting in the cache key. A response generated at temperature 0.0 (deterministic) is safe to cache and reuse. A response generated at temperature 0.7 should only be cached for cost-reduction use cases, not for correctness-sensitive applications.
Choosing and Tuning Your Similarity Threshold
The similarity threshold is the single most consequential tuning parameter in a semantic cache. Set it too low and you serve semantically unrelated responses to new queries — a correctness failure that is invisible unless you are measuring it. Set it too high and hit rates drop toward zero, eliminating the cost benefit. There is no universal correct value; it depends on your query distribution, the embedding model, and how much variation your application can tolerate.
- →Conservative (0.93–0.97): recommended as a starting point for enterprise applications where correctness matters more than hit rate. At 0.95, only near-identical paraphrases match. Hit rates at this threshold are typically 15–25% on enterprise knowledge-base workloads — still significant cost savings at scale.
- →Moderate (0.87–0.93): suitable for high-volume FAQ and customer support applications where semantic intent is stable and approximate correctness is acceptable. Hit rates of 30–45% are achievable. Requires monitoring for wrong-answer incidents.
- →Per-use-case thresholds: the most robust production design uses different thresholds by query category rather than a single global value. A billing or legal query may warrant 0.97; a general help query may work at 0.88. Route query categories to different cache namespaces with their own threshold configuration.
- →Threshold calibration: build a golden set of query pairs — similar pairs that should return the same answer, and dissimilar pairs that should not. Measure the cosine similarity distribution for each class under your chosen embedding model. Set the threshold at the point that maximizes F1 across both classes. Re-calibrate whenever you change embedding models.
Multi-Tenant Isolation: The Enterprise Security Requirement
Multi-tenant semantic caching introduces a data isolation risk that does not exist in single-tenant deployments. If two tenants share a global vector index, Tenant A's cached response can be served to Tenant B if their query is semantically similar. This is a data leak — and it happened in production in 2026: one SaaS platform saw a global semantic cache at threshold 0.88 surface one customer's account data in another customer's session. The fix is namespace isolation — the cache key and the vector index partition must include the tenant ID.
- →Tenant-scoped namespacing: include the tenant ID as a mandatory prefix in both the exact-match key (Layer 1) and the vector index partition (Layer 2). A query from Tenant A can only hit cache entries written by Tenant A. This is non-negotiable in any deployment handling multiple customers' data.
- →Namespace implementation: Redis supports key prefixing natively. Qdrant supports collection-level or payload-based filtering — use a filter on a tenant_id payload field rather than separate collections per tenant, which scale poorly above thousands of tenants. Weaviate supports multi-tenancy at the class level with per-tenant data isolation.
- →Cache poisoning defense: a maliciously crafted prompt can insert a poisoned response into the cache that will be served to future similar queries. Validate the LLM response content before caching — apply the same output validation you apply to any LLM output before storing it as a canonical answer.
- →Audit logging: log every semantic cache hit with the original query, the matched cached query, the similarity score, the tenant ID, and the response source. This is both an operational debugging tool and the forensic record if a cache-related data incident occurs.
- →Regulatory requirements: under GDPR, HIPAA, or SOC 2, tenant isolation in the cache layer is a compliance requirement. Data processed for one customer must not be accessible to another. Include the semantic cache in your data-flow documentation and compliance assessments.
Embedding Model Selection and Lookup Latency
The embedding step is mandatory overhead on every cache lookup — both hits and misses pay it. If your embedding model takes 200ms, the semantic cache can only improve latency for requests that would otherwise take more than 200ms at the LLM. The embedding model choice directly sets the floor on how much latency benefit the cache can provide.
- →OpenAI text-embedding-3-small: 20–50ms round-trip with API caching enabled. Strongest semantic quality for English-language queries. Cost: $0.02 per million tokens — negligible at scale. Embedding calls are themselves cacheable: hash the prompt and cache the embedding vector to avoid re-embedding identical prompts.
- →Local embedding models (e5-small-v2, all-MiniLM-L6-v2): 5–15ms on a co-located CPU instance. No external dependency or per-call cost. Slightly lower semantic quality than frontier embedding APIs. Recommended for high-volume, latency-sensitive applications where every millisecond matters.
- →Cohere embed-v3 / Voyage AI: strongest multilingual semantic quality and domain adaptation. 30–60ms round-trip. Recommended for enterprise deployments where queries span multiple languages or specialized domains — legal, medical, financial — where general-purpose embeddings miss domain-specific synonymy.
- →Latency budget: the total cache lookup path — embed + vector search + KV fetch — should complete under 30ms for the cache to meaningfully improve p50 latency on queries answered by fast models. For slower models or multi-step agentic pipelines, the bar is lower and larger embedding models become viable.
Observability and Cache Lifecycle Management
A semantic cache that is not instrumented is a black box that can silently serve stale or incorrect responses. Observability is how you verify the cache is improving outcomes rather than degrading them.
- →Core metrics: cache hit rate (%), cache miss rate (%), p50/p95 lookup latency (ms), estimated cost saved per hour (hits × average LLM call cost minus hits × embedding lookup cost), wrong-answer rate measured via LLM judge on a 1–2% sample of hits.
- →TTL management: most semantic cache entries should have a finite TTL. Responses to time-sensitive queries — pricing, availability, live data — should carry short TTLs (minutes) or not be cached at all. Timeless factual responses — documentation, how-to guides — can carry longer TTLs (days to weeks).
- →Prompt-version invalidation: when you update your system prompt or change your response format, previously cached responses are no longer valid. Include a prompt-version token in the cache key so deploying a new system prompt automatically invalidates the old cache without a full flush.
- →Quality monitoring: run an LLM judge that evaluates whether the cached response correctly answers the incoming query — not just the stored canonical query. Alert when the wrong-answer rate on cache hits exceeds 2%. A rising wrong-answer rate is a signal the similarity threshold is set too low.
When Semantic Caching Earns Its Overhead
Semantic caching is not a universal optimization. It adds infrastructure complexity, introduces an embedding latency floor, and requires ongoing threshold tuning and quality monitoring. Before deploying it, measure your actual query repetition rate. If fewer than 20% of queries are semantically equivalent to something in your history, the embedding overhead will cost more than the cache saves.
- →High-value use cases: customer support chatbots where 80–90% of support questions repeat across customers; internal knowledge-base Q&A where employees repeatedly ask the same policy questions; documentation assistants; sub-question answering inside agentic RAG pipelines where decomposed sub-queries repeat across sessions.
- →Low-value use cases: personalized recommendation or analysis where outputs are user-specific and must not be shared; creative generation at high temperature where responses should vary; real-time data queries where responses are stale by definition; long-context document summarization where input variation is too high for semantic matching to capture.
- →Agentic pipelines: semantic caching in agentic systems should be applied at the sub-question level, not the full user intent level. A ReAct or Plan-and-Execute agent decomposes a user query into 3–7 sub-queries; individual sub-queries like 'What is the Q3 revenue for the APAC region?' repeat across user sessions even when top-level questions are unique. Instrument caching at the tool-call level within the agent, not at the agent input level.
- →Break-even analysis: if your average LLM call costs $0.02 and your embedding lookup costs $0.0002, you break even at a 1% cache hit rate. Most enterprise FAQ workloads see 30–50% hit rates. The question is not whether the economics work — they almost always do — but whether your specific workload has enough repetition to justify the implementation complexity.
Frequently Asked Questions
What is semantic caching for LLMs?
Semantic caching is a request-level cache layer that embeds incoming prompts into vectors and returns a stored response when the new prompt is semantically similar to a previously answered one — without making a new LLM API call. Unlike exact-match caching, it matches on meaning rather than character identity, enabling high hit rates on query-repetitive workloads even when users phrase questions differently.
How is semantic caching different from prompt caching?
Prompt caching is a server-side provider feature that caches KV-attention state for repeated system-prompt prefixes and charges a reduced rate on reuse — it lowers cost per call but does not eliminate the API call. Semantic caching is a client-side layer that intercepts the request before it reaches the provider and returns a fully computed cached response, eliminating the API call entirely. Both are complementary and should be deployed together for maximum cost reduction.
What similarity threshold should I use for semantic caching?
Start at 0.95 and measure hit rate and wrong-answer rate on a sample of production traffic. If hit rates are below 15% with correct answers, lower the threshold incrementally. If wrong-answer rates exceed 1–2%, raise the threshold. The correct value is workload-specific; a global threshold rarely optimizes well across mixed query types. The most robust approach is per-category thresholds with separate cache namespaces.
Is semantic caching safe for multi-tenant enterprise applications?
Only when tenant isolation is strictly enforced. A shared semantic cache without per-tenant namespacing is a data leak vector — a cached response from one customer's session can be served to another if their query is semantically similar. Namespace both the vector index and the exact-match KV store by tenant ID. This is a security requirement, not an optional optimization.
Which tools implement semantic caching for LLMs?
GPTCache (open source, Python) is the most widely adopted standalone semantic cache library. Redis Stack with Vector Search supports semantic caching as a first-class feature from Redis 7.2+. Qdrant, Weaviate, and Pinecone all provide the vector index component. LangChain and LlamaIndex include semantic cache integrations. Managed options — Portkey AI, Helicone, and LangSmith — offer semantic caching as part of their LLM observability and gateway platforms.
How Belsoft Helps With LLM Cost Optimization
Semantic caching is one layer of a full LLM cost-optimization stack. At Belsoft, we implement the complete production architecture — gateway, semantic cache with tenant isolation, prompt caching configuration, model routing, and cost observability dashboards — as part of our AI & Automation engineering service. Teams that engage us typically reduce their LLM infrastructure spend by 40–60% within the first month of production deployment, without changing user-facing product behavior.
If you are scaling an LLM-powered product and the API bill is growing faster than revenue, the right time to instrument caching is before you optimize inference — caching eliminates calls that optimization would merely make cheaper. Book a technical review and we will profile your query distribution, estimate your cache hit rate, and design the isolation architecture appropriate for your compliance requirements.
“The cheapest LLM call is the one you never make.”
Written by
Belal Hisham
Founder & Lead Engineer, Belsoft Solutions
More from the blog
Ready to build?
Let's talk about your project.
30 minutes. No pitch. We map your requirements and tell you honestly what it will take.
Book a Strategy Call