> ## Documentation Index
> Fetch the complete documentation index at: https://docs.wardin.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Caching

> Two distinct caching mechanisms that reduce spend without changing your prompts.

Wardin has two caching layers. They are distinct mechanisms — don't conflate them.

## 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:

* `temperature` is **explicitly set to `0`** (omitted temperature uses the provider's non-deterministic default, so it is *not* cacheable)
* No streaming (`"stream": false` or omitted)
* No tools / function calling (an empty `tools` array is fine)

Cache hits are marked with the `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 the `X-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-side `cache_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`          |

If these are blended, cost dashboards for agentic traffic (Claude Code, Cursor) will be significantly wrong. Wardin never blends them.

## Cache metrics

```
Total savings = (exact_hit_tokens × model_input_price)
              + (semantic_hit_tokens × model_input_price)
              + (cache_read_tokens × (full_price - read_price))
```

The dashboard shows these three numbers separately so you know which savings carry zero risk (exact) vs approximation risk (semantic) vs provider-level savings (prompt cache).
