The shared semantic-cache example has no tenant isolation key and may return one customer's AI response to another
Source references: 7The complete policy performs a semantic cache lookup inbound and stores the response outbound, but shows no partitioning by subscription, user, or tenant. The multi-tenant example derives tenantId for limits and metrics but still does not apply it to caching.
Similar prompts from different tenants could reuse a response containing another tenant's context, business data, or personalized content. A lower similarity threshold broadens the range of potentially incorrect matches.
The example performs semantic cache lookup and storage without showing a tenant key, while the multi-tenant example uses tenantId only for limits and metrics. However, the supplied source does not document APIM's actual semantic-cache scope, so absence of an explicit key alone does not establish cross-tenant sharing. Users should ask the author to document the default scope and verify isolation before multi-tenant deployment.
This assessment concerns the code and conditions shown, not proof that harm has occurred. <!-- 2. Semantic Cache Lookup --> <azure-openai-semantic-cache-lookup score-threshold="0.8" embeddings-backend-id="embeddings-backend" embeddings-backend-auth="system-assigned" /> <!-- 3. Token Rate Limiting --> <azure-openai-token-limit tokens-per-minute="50000" counter-key="@(context.Subscription.Id)" estimate-prompt-tokens="true" />Show 6 other places
<outbound> <base /> <!-- Cache store (after successful response) --> <azure-openai-semantic-cache-store duration="3600" /> </outbound> <base /> <!-- Extract tenant from subscription or header --> <set-variable name="tenantId" value="@(context.Subscription.Id)" /> <!-- Per-tenant token limit --> <azure-openai-token-limit tokens-per-minute="10000" counter-key="@((string)context.Variables["tenantId"])" estimate-prompt-tokens="true" /> <!-- Per-tenant metrics --> <azure-openai-emit-token-metric namespace="ai-gateway"> <dimension name="Tenant" value="@((string)context.Variables["tenantId"])" />| Cause | Fix ||-------|-----|| `score-threshold` too high | Lower from 0.9 to 0.7 (more matches) || Embeddings backend misconfigured | Verify backend URL and auth || Redis not configured | Deploy Azure Cache for Redis Enterprise with RediSearch || Streaming requests | Semantic caching doesn't work with `"stream": true` |```xml<azure-openai-semantic-cache-lookup score-threshold="0.8" embeddings-backend-id="embeddings-backend" embeddings-backend-auth="system-assigned" />```**Store** (in `<outbound>`):```xml<azure-openai-semantic-cache-store duration="3600" />``` <!-- Extract tenant from subscription or header --> <set-variable name="tenantId" value="@(context.Subscription.Id)" /> <!-- Per-tenant token limit --> <azure-openai-token-limit tokens-per-minute="10000" counter-key="@((string)context.Variables["tenantId"])" estimate-prompt-tokens="true" /> <!-- Per-tenant metrics --> <azure-openai-emit-token-metric namespace="ai-gateway"> <dimension name="Tenant" value="@((string)context.Variables["tenantId"])" /> <dimension name="API" value="@(context.Api.Name)" />