Scenario
We run GPT-5.6 deployments on a Standard pay-as-you-go Azure OpenAI resource in Sweden Central and rely on prompt caching to keep input cost down for long, stable system prompts.
The documentation states for GPT-5.6:
prompt_cache_options.ttl sets a minimum cache lifetime. [...] A cached prefix
remains eligible for reuse for at least 30 minutes, but the service might
retain it longer.
— Prompt caching with Azure OpenAI
We measure a cached prefix disappearing in under 8 minutes of inactivity, which matches the pre-GPT-5.6 in-memory policy ("typically clears caches within 5 to 10 minutes of inactivity") that the same article says no longer applies to GPT-5.6.
Environment
- Azure OpenAI, Standard pay-as-you-go, region Sweden Central
- Deployments:
gpt-5.6-terra, gpt-5.6-sol, gpt-5.6-luna
- v1 API:
POST {endpoint}/openai/v1/responses and /openai/v1/chat/completions
- Plain HTTPS requests, Python standard library only, no SDK involved
The deployments are Standard, not PTU-M: they report cache_write_tokens and accept prompt_cache_breakpoint, neither of which PTU-M supports.
Repro
A byte-identical ~4,015-token prefix is sent at 0 min, +8 min, +20 min and +35 min. prompt_cache_key is set on every request, and the request rate is 3 requests per checkpoint, far below the documented ~15/min threshold.
import json, time, urllib.request
from datetime import datetime
URL = "https://<resource>.openai.azure.com/openai/v1/responses"
KEY = "<api key>"
PREFIX = "Please ignore this test text. " * 500 # ~4,000 tokens
def call(label):
body = {
"model": "gpt-5.6-terra",
"max_output_tokens": 16,
"prompt_cache_key": "probe-a",
"input": [{"type": "message", "role": "user", "content": [
{"type": "input_text", "text": PREFIX},
{"type": "input_text", "text": "Reply with the word OK."},
]}],
}
req = urllib.request.Request(
URL, data=json.dumps(body).encode(),
headers={"Content-Type": "application/json", "api-key": KEY},
)
with urllib.request.urlopen(req, timeout=120) as resp:
u = json.load(resp)["usage"]
d = u["input_tokens_details"]
print(f"{datetime.now():%H:%M:%S} {label:10} input={u['input_tokens']} "
f"cached={d.get('cached_tokens', 0)} writes={d.get('cache_write_tokens')}")
call("warmup")
call("immediate")
time.sleep(8 * 60)
call("+8 min")
time.sleep(12 * 60)
call("+20 min")
time.sleep(15 * 60)
call("+35 min")
Result
Three request shapes were sent side by side, each with its own prefix and prompt_cache_key:
| Variant |
Request shape |
| A |
default implicit mode, no explicit breakpoint |
| B |
prompt_cache_options {mode: implicit, ttl: 30m} + prompt_cache_breakpoint on the input_text block |
| C |
prompt_cache_options {mode: explicit, ttl: 30m} + prompt_cache_breakpoint on the input_text block |
11:15:45 warmup A input=4014 cached=0 ( 0.0%) writes=4011
11:15:46 warmup B input=4015 cached=0 ( 0.0%) writes=4012
11:15:47 warmup C input=4015 cached=0 ( 0.0%) writes=4004
11:15:48 immediate A input=4014 cached=4011 ( 99.9%) writes=0
11:15:50 immediate B input=4015 cached=4012 ( 99.9%) writes=0
11:15:52 immediate C input=4015 cached=4004 ( 99.7%) writes=0
11:23:53 +8 min A input=4014 cached=0 ( 0.0%) writes=4011
11:23:54 +8 min B input=4015 cached=0 ( 0.0%) writes=4012
11:23:55 +8 min C input=4015 cached=0 ( 0.0%) writes=4004
11:35:57 +20 min A input=4014 cached=0 ( 0.0%) writes=4011
11:35:58 +20 min B input=4015 cached=0 ( 0.0%) writes=4012
11:35:59 +20 min C input=4015 cached=0 ( 0.0%) writes=4004
11:51:00 +35 min A input=4014 cached=0 ( 0.0%) writes=4011
11:51:01 +35 min B input=4015 cached=0 ( 0.0%) writes=4012
11:51:03 +35 min C input=4015 cached=0 ( 0.0%) writes=4004
The writes value on every cold call shows the prefix being written to the cache again, so this is eviction rather than a routing miss. Because cache writes are billable on GPT-5.6, each request after a short pause costs more than an uncached request would have.
Control: the same model on OpenAI direct keeps the prefix
To rule out that this is simply how GPT-5.6 caching behaves, the same prefix was sent to gpt-5.6-terra through the OpenAI API instead of Azure, using the same script and the same intervals:
13:40:02 warmup input=5014 cached=0 ( 0.0%) writes=5011
13:40:04 immediate input=5014 cached=5011 ( 99.9%) writes=0
13:46:07 +6 min input=5014 cached=5011 ( 99.9%) writes=0
14:00:10 +20 min input=5014 cached=5011 ( 99.9%) writes=0
On OpenAI the prefix is still fully cached after 20 minutes and writes stays 0, meaning the original entry is being read rather than rewritten. On Azure the same model has already lost the entry at +8 min and pays a fresh cache write. The model and the request shape are identical; only the provider differs.
Troubleshooting already done
Each of these was measured, not assumed. All variables below made no difference:
- Network path — identical results through our reverse proxy and when calling
the Azure endpoint directly.
- API surface — identical results on
/openai/v1/responses and
/openai/v1/chat/completions, same deployment, same moments.
- Explicit breakpoints — variants B and C follow the documented example
(breakpoint on an
input_text / text content block).
- Deployment —
terra, sol and luna were sent the same payload at the
same moments and all three lost the prefix between the immediate call and
+8 min.
- Prefix stability — the payload is generated once per process and reused
byte-for-byte; 4,015 tokens, well above the 1,024 minimum.
- Request rate — 3 requests per checkpoint, far below ~15/min per key.
Question
Is the documented 30-minute minimum cache lifetime actually in effect for GPT-5.6 Standard pay-as-you-go deployments in Sweden Central? The same model reached through the OpenAI API retains the prefix for at least 20 minutes, so this does not appear to be inherent to GPT-5.6 caching. If these deployments are still served by the pre-GPT-5.6 in-memory retention policy, is there a configuration on our side that enables the documented behaviour?
These describe a different failure (cached_tokens returning 0 on every call).
In our case caching works and then expires early, so they are not duplicates: