Semantic Caching for LLMs: How It Works and the Tools That Do It
TL;DR
- Semantic caching for LLMs serves a stored response when a new request's embedding falls within a similarity threshold of a cached one, so paraphrased repeats skip the model call.
- Bifrost runs an exact hash lookup first and a semantic lookup only on a miss, so identical requests never pay for an embedding call.
- A semantic hit still costs one embedding round-trip, and a semantic miss adds that cost on top of the full LLM call, which is why threshold tuning matters.
- Bifrost caches chat completions, text completions, the Responses API, embeddings, transcriptions, speech, and image generation, including streaming variants.
- Semantic caching operates at three layers: gateway-native caching, library-level caching such as GPTCache, and the vector databases both are built on.
Semantic caching for LLMs matches an incoming request against previously cached responses using vector similarity, rather than exact-string comparison, so a rephrased duplicate query can be served from cache instead of triggering a new call to the model provider. This is different from a plain key-value cache, which only returns a hit when the new request is character-for-character identical to something already stored. Bifrost, the open-source AI gateway built in Go by Maxim AI, implements semantic caching at the gateway layer, so every provider behind it benefits from the same cache without any application-level integration work. This post covers how semantic caching works, what it costs in latency and infrastructure, and how the tools that implement it compare.
For the cost side of the same topic, see how semantic caching cuts LLM token spend with AI gateways.
What Is Semantic Caching for LLMs
Semantic caching for LLMs is a technique that stores a model response alongside a vector embedding of the request, then serves that stored response when a new request's embedding falls within a similarity threshold of one already cached, even if the wording is different.
Most implementations, including Bifrost's semantic caching, actually combine two lookup paths:
- Direct (hash) matching: the request is normalized and hashed; an identical request is served instantly, with no embedding step involved.
- Semantic (similarity) matching: an embedding-based lookup that serves a cached answer when a new request is close enough to a previous one in vector space, even when the exact phrasing differs.
Bifrost runs direct matching first and falls back to semantic matching only on a direct miss, so exact repeats never pay the cost of an embedding call. Direct-only mode is available with no embedding provider configured at all, which is useful for workloads with stable, repeated prompts rather than varied paraphrasing. The technical deep dive on semantic caching covers the embedding and similarity math in more detail.
Semantic Caching vs Prompt Caching
Semantic caching and prompt caching are different mechanisms that can run together. Semantic caching replays a response the gateway has already seen, so the model provider is never called. Prompt caching is the provider reusing the prefix of a request, so the call still happens and is still billed, at a lower rate for cached input.
| Semantic caching | Provider prompt caching | |
|---|---|---|
| Where it runs | AI gateway or application layer | Model provider |
| What is reused | The full stored response | The processed request prefix |
| Provider call made | No, on a cache hit | Yes |
| Billing on a hit | No model charge; semantic mode adds one embedding call | Reduced input-token rate; cache writes can cost more than fresh input |
| Matches paraphrases | Yes, in semantic mode | No, the prefix must be identical |
Why Semantic Caching Matters for LLM Costs and Latency
Cutting duplicate model calls is the direct payoff, and the scale of that cut can be substantial. GPTSemCache, a semantic caching system summarized in a 2026 arXiv paper on semantic caching policies, reported cache hit rates between 61.6% and 68.8% across varied query categories and a reduction in API calls of up to 68.8%, meaning a similar share of requests never had to reach the model provider at all.
The practical benefits break down into three areas:
- Cost reduction: a cache hit replaces a full model call with a stored response, which is the largest lever available for workloads with repeated or paraphrased questions (FAQ bots, support assistants, internal knowledge tools).
- Lower latency: a direct cache read is a single vector store round-trip, typically sub-millisecond to a few milliseconds with a local Redis or Valkey store (semantic reads add an embedding call), versus a multi-second round trip to a model provider.
- Reduced provider load: fewer calls per unique piece of information reduces exposure to provider-side rate limits during traffic spikes.
The guide to optimizing LLM cost and latency with semantic caching works through these trade-offs with example workloads.
The tradeoff is that semantic lookups are not free. A semantic hit still costs one embedding call before the similarity search runs, and a semantic miss pays that embedding cost on top of the full model call that follows, which is why the direct-then-semantic ordering matters operationally.
How Semantic Caching Works
Semantic caching works by checking each request against stored responses before it reaches the model: an exact hash match first, then an embedding similarity search, with new responses written back after the provider replies. A semantic caching layer sits in the request path and follows the same general flow across most implementations:
- A request arrives carrying a cache key (in Bifrost, the
x-bf-cache-keyheader or an SDK context value). Requests without a cache key bypass the cache entirely unless adefault_cache_keyis configured. - Direct hash lookup runs first. If the normalized request matches a stored hash exactly, the cached response is served immediately.
- On a direct miss, the request is embedded using a configured embedding model, and a vector similarity search runs against the cache store.
- If the similarity score clears the configured threshold, the cached response is served. If not, the request proceeds to the model provider as normal.
- The new response is written back to the cache asynchronously, so the first occurrence of a new question is never slowed down by the cache write itself.
Threshold tuning is the main operational lever: too loose a threshold returns answers for questions that are only superficially similar, while too tight a threshold misses obvious paraphrases and rarely produces a hit at all. Most teams tune this against a sample of real query logs before shipping to production rather than picking a value up front.
Bifrost lets individual requests override the LLM cache defaults through request headers:
| Header | Effect |
|---|---|
x-bf-cache-key |
Scopes the request to a cache partition; required unless a default key is set |
x-bf-cache-ttl |
Overrides the time-to-live for this request's cache entry |
x-bf-cache-threshold |
Overrides the semantic similarity threshold, from 0 to 1 |
x-bf-cache-type |
Limits the lookup to direct or semantic |
x-bf-cache-no-store |
Serves cached hits but skips writing the new response |
A vector store is required as the backing storage layer for both direct and semantic modes. Bifrost's vector store supports Redis and Valkey for in-memory deployments, along with Weaviate, Qdrant, and Pinecone for teams already standardized on one of those.
Redis's own vector search documentation covers how K-nearest-neighbor lookups work at the storage layer, which is the same underlying mechanism a semantic cache relies on.
The Tools That Implement Semantic Caching
Semantic caching for LLMs shows up at three different layers of the stack, and which one fits depends on where the caching logic should live. For ranked comparisons of specific products, see the top semantic caching solutions for AI apps and the AI gateways with semantic caching that cut LLM API calls.
Gateway-native caching. Bifrost applies semantic caching as an AI gateway that already sits between an application and every model provider it uses, which makes the gateway a natural AI caching layer. Because Bifrost is already in the request path for routing and failover, adding caching does not require a separate integration; it is a plugin that runs on the same traffic and loads live without a server restart.
This means every application behind the gateway shares one cache, cache hit and miss data shows up in the same observability dashboards as request volume and cost, and turning caching on or off is a configuration change rather than a code change. Bifrost supports both direct and semantic modes, per-model and per-provider cache scoping, and streaming responses cached and replayed chunk-by-chunk. Teams migrating from another gateway can follow the migration guide to a gateway with native semantic caching.
Library-level caching. GPTCache, an open-source project maintained by Zilliz, is a library-level option. GPTCache wraps directly into Python application code, integrates with LangChain and LlamaIndex, and uses a modular architecture where the embedding model, vector store, and eviction policy can each be swapped independently; a Docker server image is also available for non-Python services. This fits teams that want caching logic to live inside a single application rather than at shared infrastructure, though each service running its own GPTCache instance means a separate cache per deployment rather than one shared cache across an organization's traffic.
Vector database infrastructure. Redis, Weaviate, Qdrant, and Pinecone are the storage layer underneath most semantic caching implementations, gateway-native or library-level. As vector databases, these provide the vector index that a caching layer (like Bifrost or GPTCache) is built on top of, while request routing and cache-key composition sit in that caching layer.
| Layer | Example | Where caching logic lives | Cache scope |
|---|---|---|---|
| Gateway-native | Bifrost | AI gateway in front of every provider | Shared across every application behind the gateway |
| Library-level | GPTCache | Inside each application or its sidecar server | One cache per service deployment |
| Vector database | Redis, Valkey, Weaviate, Qdrant, Pinecone | Vector index and similarity search | Whatever the caching layer above defines |
The practical difference between these categories is where caching logic lives and how many places it has to be configured. A single organization running several services behind one gateway gets one cache and one place to tune it with a gateway-native approach; the same organization using a library-level approach configures caching separately in every service that needs it.
Key Considerations When Implementing Semantic Caching
Caching LLM responses safely depends on cache scoping, threshold tuning, cache-key composition, and support for streaming and multi-turn conversations. Getting these wrong can serve one user's answer to another or replay a response from the wrong model. A few details determine whether semantic caching helps or introduces new problems:
- Personalized or user-specific responses should not share a cache scope. If a prompt encodes user-specific context, two structurally similar requests can be semantically distinct, and a shared cache can return the wrong user's data.
- A similarity threshold has to be tuned, not assumed. The right value depends on the vocabulary and phrasing diversity of real traffic, and it should be validated against logged queries before enabling caching in production.
- TTL and cache-key composition affect correctness as much as hit rate. A cache key that ignores model or provider differences can serve a response generated by one model in place of another; Bifrost's semantic caching configuration includes per-model and per-provider cache-key composition for exactly this reason.
- Streaming responses need explicit support. Caching a streamed response requires replaying it chunk-by-chunk rather than caching only the final assembled output.
- Long conversations rarely repeat. Bifrost skips caching when a conversation exceeds a configurable message count (
conversation_history_threshold, three by default), and can exclude system prompts from cache-key generation.
Teams evaluating tools for this should start from the Bifrost resources hub, which also covers how caching fits alongside the rest of an AI gateway's governance and routing capabilities. Cost reduction from caching also pairs directly with other gateway-level cost controls; the MCP Gateway covers a separate token-cost reduction achieved through tool-call optimization rather than response caching.
Frequently Asked Questions
What is semantic caching in LLMs?
Semantic caching in LLMs stores a model response together with an embedding of the request, then returns that stored response when a new request is similar enough in meaning, even if the wording differs. It avoids a new call to the model provider, which reduces cost and latency for repeated or paraphrased questions.
How does LLM caching work?
LLM caching intercepts requests before they reach a model provider. An exact cache matches a normalized hash of the request, while a semantic cache embeds the request and runs a vector similarity search against stored entries. On a hit, the stored response is returned; on a miss, the provider response is returned and written to the cache asynchronously.
Is semantic caching the same as prompt caching?
No. Semantic caching replays a complete stored response, so the provider is not called on a hit. Provider prompt caching reuses the processed prefix of a request, so the call still happens and is billed at a reduced rate for cached input. Bifrost supports both, and they can run at the same time.
How do you cache LLM responses safely?
Scope cache keys so user-specific prompts never share a partition, tune the similarity threshold against real query logs, and include the model and provider in cache-key composition. In Bifrost, the x-bf-cache-key header sets the partition, and cache_by_model and cache_by_provider keep responses from one model from being served for another.
Which vector databases work with semantic caching?
Bifrost semantic caching supports Redis and Valkey for in-memory deployments, plus Weaviate, Qdrant, and Pinecone, all configured through the Bifrost vector store layer. A vector store is required for both direct and semantic modes, even though direct-only mode generates no embeddings. Library-level tools such as GPTCache support their own set of stores, including Milvus, Zilliz Cloud, and FAISS.
Getting Started with Semantic Caching in Bifrost
Semantic caching for LLMs is a direct way to cut both cost and latency for applications with any amount of repeated or paraphrased traffic, and it works best when it sits at the same layer already handling provider routing and governance rather than as a separate integration per service. The same gateway can pair caching with budgets and rate limits on virtual keys, and the gateway approach to cutting LLM token spend shows the combined effect.
Bifrost deploys with zero configuration as a drop-in replacement for existing OpenAI or Anthropic SDK calls, so existing traffic can route through Bifrost by changing a base URL, and caching is then enabled by configuring the plugin, with no application rewrite.
To see semantic caching running alongside routing, failover, and cost governance in one gateway, book a demo with the Bifrost team.