Isolate semantic cache entries by tenant
- Applies to
- Gatewayruntime for API, AI, and MCP gatewaysEnterprise add-on
- Hosting
- Managed EdgeManaged DedicatedSelf-Hosted
The Semantic Cache policy
(semantic-cache-inbound) answers a request from an earlier response when the
new request means the same thing, even when the wording differs. That makes it a
good fit in front of an LLM or a natural-language search API. When several
tenants share a route, give each tenant its own namespace so that one
tenant's cached answer never reaches another tenant.
A namespace partitions the cache. A lookup only matches entries stored in the same namespace, and the policy stores a response in the namespace of the request that produced it.
Set the namespace for each request
Set cacheBy to function and point cacheByFunction at a function in your
project. The policy calls the function on each request. The function returns the
cache key and, optionally, settings for that request only:
| Property | Required | What it does |
|---|---|---|
cacheKey | Yes | The text the policy compares by meaning, such as the user's question. |
namespace | No | The partition to look up and store this request in. |
semanticTolerance | No | How far apart two keys can be and still match. Smaller values match closer. |
expirationSecondsTtl | No | How many seconds to keep a response that this request stores. |
A value the function returns overrides the policy option of the same name for
that request. A value it leaves out falls back to the policy option. With no
namespace from either, the policy uses the default namespace.
This function uses the question in the request body as the key and the authenticated caller as the namespace:
modules/semantic-cache-key.ts
Read the body from request.clone(), as in the example. Reading the original
request consumes the body before it reaches your backend.
If the function throws, or returns no string cacheKey, the policy logs an
error and the request continues to the backend without caching.
Configure the policy
Reference the function in the policy options:
config/policies.json
Add the policy to the route after your authentication policy, so that the
function can read request.user:
config/routes.oas.json
With returnCacheStatusHeader set to true, every response carries a
zp-semantic-cache header with HIT or MISS. Set cacheStatusHeaderName to
use a different header name.
Check the results
Send a question twice with one API key, then once with a key for a different consumer:
| Request | zp-semantic-cache |
|---|---|
| Consumer A asks a question | MISS |
| Consumer A asks it again | HIT |
| Consumer B asks the same question | MISS |
To watch hit rates over time, open Observability → Analytics in your project and select the Cache section. The Policies table shows hits, misses, and hit rate for each caching policy.
AI Gateway apps
For traffic through the AI Gateway, use the AI Gateway Semantic Cache policy in the app's policy chain. It keys on the prompt for you and keeps each app's cached responses apart, and the tokens its hits save appear as Saved Tokens in the Cache analytics.