L1: Exact-match cache
A Redis-backed cache keyed on a deterministic hash of the request body (model + messages + params). On a hit, the cached response is returned immediately at $0 cost — the request never reaches the provider. Eligibility — a request is cache-eligible when all of these are true:temperatureis explicitly set to0(omitted temperature uses the provider’s non-deterministic default, so it is not cacheable)- No streaming (
"stream": falseor omitted) - No tools / function calling (an empty
toolsarray is fine)
X-Wardin-Cache: HIT response header.
Tenant scoping — cache keys are always prefixed with tenant_id. A cross-tenant cache hit is impossible by construction.
Dashboard — the ROUTE stage shows the cache split (exact vs. semantic hits) with savings calculated at the model’s full input price; exact and semantic are never blended into one number.
L2: Semantic cache (pgvector)
A vector similarity cache backed by pgvector. When an incoming prompt has no exact match, its embedding is compared against stored embeddings. If similarity ≥ the configured threshold (default 0.92), the cached response is returned. Semantic hits are approximate — the response was generated for a similar but not identical prompt. The dashboard separates these from exact hits because they carry approximation risk. Semantic hits are marked with theX-Wardin-Cache: SEMANTIC response header.
Threshold — configurable per tenant in Console → Cache. Raise it for more conservative matching; lower it for a higher hit rate with more approximation. Threshold changes are recorded to the EVIDENCE audit trail.
Bypass — set "stream": true, include tools, or use a non-zero (or omitted) temperature to bypass both cache layers for that request.
Provider-native prompt caching (Anthropic)
This is not Wardin’s cache — it’s Anthropic’s server-sidecache_control feature. Wardin passes cache_control blocks through unmodified and parses the resulting token types from the response separately:
| Token type | Cost multiplier | Wardin field |
|---|---|---|
cache_creation_input_tokens | 1.25× | cache_creation_cost_usd |
cache_read_input_tokens | 0.1× | cache_read_cost_usd |
Regular input_tokens | 1.0× | input_cost_usd |