Skip to content

Caching

An opt-in exact-match response cache, and the provider-side prompt caching it is not.

5 min read

Opt-in, always

Nothing is cached unless the request asks for it. A gateway that cached by default would silently make every application non-deterministic — the same call returning a frozen answer an hour later, with no way to tell from the outside that it had.

Ask for it with a header carrying the number of seconds you want the answer kept:

bash
curl https://api.multigrid.ai/v1/chat/completions \
  -H "Authorization: Bearer $MULTIGRID_API_KEY" \
  -H "Content-Type: application/json" \
  -H "X-Multigrid-Cache-Ttl: 3600" \
  -d '{
    "model": "openai/gpt-5-nano",
    "messages": [{"role": "system", "content": "Classify as billing, bug or feature."},
                 {"role": "user", "content": "My card was charged twice."}]
  }'

# A hit answers with:
#   X-Multigrid-Cache: hit
#   X-Multigrid-Cost-Usd: 0.000000
#   "multigrid": { "cache": "hit", "cost_micros": 0, "saved_usd": 0.000021, … }

A hit costs nothing, reaches no provider, and reports what it saved. A streaming caller gets a hit replayed as StreamingThe answer arrives word by word as it is written, instead of all at once at the end. It costs the same; it just feels far faster., because their SDK is already in streaming mode and would choke on anything else — in one chunk, since pretending to type it out slowly would be theatre.

What makes two requests the same

The cache key is a SHA-256 over twelve named fields: your account id, model, models, the whole message list, temperature, top_p, top_k, max_tokens, stop, tools, tool_choice, response_format and seed.

Some parameters that change the answer are not in the key
frequency_penalty, presence_penalty, logit_bias, reasoning_effort and logprobs are not hashed. Two requests that differ only in one of those are the same request as far as the cache is concerned, so the second one gets the first one’s answer. If you are sweeping any of those to compare outputs, do not turn the cache on for that work — it is opt-in per request, so leaving cache off is the whole fix. Everything the cache serves is your own earlier answer, never another account’s.
The account id is inside the hash, not beside it
A cache shared between customers would serve one company’s completion to another. That is a data breach dressed as an optimisation, so the isolation is a property of the key itself rather than a filter applied afterwards.

stream is deliberately not part of the key: the same question streamed and unstreamed has the same answer, so a streaming caller can be served from a non-streaming caller’s entry. Your user field and routing hints are excluded too — they change who asked and where it ran, not what comes back.

Matching is exact. Two prompts differing by one character are two different requests.

Rules and limits

RuleDescription
TTLWhatever you ask for, capped at 24 hours. Beyond a day, “the model changed” becomes the likelier truth. A TTL of 0 means “definitely do not cache this one”.
Successes onlyAn error is exactly the thing you want retried, not remembered.
No empty answersA waived zero-completion response is not stored — caching it would serve the same nothing for the whole TTL.
Non-streaming writesOnly complete responses are written. Rebuilding a completion, tool calls included, out of a token stream is the kind of reconstruction that is right in testing and subtly wrong in production.
256 KBLarger bodies are not stored. The win is on repeated small calls.
Never with web searchA request carrying the web plugin is not cached whatever you asked for. Replaying yesterday’s search under today’s timestamp would return stale sources while still claiming they had just been retrieved.

Hit counts and the last hit time are kept per entry, and the Cache page shows what is live and what it has saved you.

Provider-side prompt caching

This is a different thing that you also benefit from, and it is not something you switch on here. Several providers cache the leading portion of a prompt on their own side and charge a fraction of the normal rate for it. When they report that, the count arrives as usage.prompt_tokens_details.cached_tokens and those tokens are billed at the route’s cached rate rather than the full prompt rate.

So: the cache above skips the provider entirely and costs nothing; prompt caching still calls the provider and costs less. Both show up on the same response, and only the first is yours to control.

Something here disagrees with what the API actually did? That is a bug in this page, and worth reporting.

Report it