Detect system-field leak
What you'll learn
If anything that changes per call (date, user ID, request UUID) ends up in the system prompt, you've leaked. It breaks caching and pollutes the privileged role.
- System-field leak = volatile per-request data in the system prompt.
- Two consequences: cache breaks (key changes per call) + privileged-layer pollution.
- Detect via low cache hit rate, high cost on supposedly cached endpoints, code review.
A 'system-field leak' is when volatile, per-request data ends up in the `system` field of the Messages API. It looks innocuous (it's just text), but it has two structural consequences: it busts prompt caching (the cache key changes per call so you cache-miss every time), and it puts user-/request-specific data into the privileged role layer where the model treats it as more authoritative than user content.
Canonical leaks: today's date interpolated into the system prompt, the current user's name or ID, a request UUID, the timestamp of the call, the user's geolocation, IP address, session token. None of these belong in `system` because none of them are stable across calls. They belong in the user message (often as a labelled field at the top of the user content: 'Current date: 2026-05-02. Question: …').
Detection signature: cache hit rate is unexpectedly low (should be near 1.0 for a stable prefix; if it's 0.0, look for volatile data in the prefix). Or: per-call latency / cost on what should be a heavily-cached endpoint is suspiciously high. Or: a code review reveals that the system-prompt construction reads from a per-request variable. Any of these is the same underlying leak.
The fix is mechanical: move the volatile data out of `system` into the `user` field (or into a separate user-message variable below the cache_control marker). Re-establish the byte-stable system prefix. Cache hit rate jumps; cost falls; the privileged-layer pollution stops. This pairs tightly with B3.4 (cache placement) — the leak is the most common reason the cache that 'should' work doesn't.
Key points
- System-field leak = volatile per-request data in the system prompt.
- Two consequences: cache breaks (key changes per call) + privileged-layer pollution.
- Detect via low cache hit rate, high cost on supposedly cached endpoints, code review.
- Fix: move volatile data into the user message, re-establish byte-stable system prefix.
Examples
system: f'You are a support agent. The current date is {today}. Today's special offer: {special}.' user: '<question>' The system prefix changes daily (date + offer). Cache is invalidated every day; per-call cost stays high; daily-changing offer pollutes the privileged role.
system: 'You are a support agent.' [cache_control: ephemeral] user: 'Current date: 2026-05-02. Today's special offer: {special}. Question: <question>' System is byte-stable across calls; cache hits; volatile data lives in user content where it belongs.
Pitfalls
- Assuming 'small' volatile data (just a date) is harmless. The cache cares about exact bytes; one-character drift invalidates the entire prefix.
- Treating the system field as 'just a place to put text.' It's privileged role context with cache implications.
- Hunting cache misses by examining the user message instead of the system prefix. The leak is almost always upstream.
Source notes: 00-academy-basics/notes/04-claude-api.md
Ask Claude
Build a prompt with this lesson + your question, copy it, and open the Claude Project in a new tab.