๐ง What is Prompt Caching?
When you send a large input context (e.g. a long document, system prompt, or reference text) to an LLM, the provider processes all those tokens every time โ which costs money and takes time.
Prompt caching lets providers reuse the processed version of that input if they see it again soon, so you pay less and get faster responses.
๐ก Think of it like a browser cache โ instead of re-downloading the same page, it serves it from memory.
๐ฌ LiteLLM Demo โ Seeing Caching in Action
( Level2 โ part1.ipynb )
Import LiteLLM in Case you havenโt
โถ๏ธ Create a new code cell and run it:
from litellm import completionLoad the context (Hamlet.txt)
download from below link:
https://github.com/codevedadev/ai-engineering-core/blob/main/level2/hamlet.txt
โถ๏ธ Create a new code cell and run it:
with open("hamlet.txt", "r", encoding="utf-8") as f:
hamlet = f.read()
loc = hamlet.find("Speak, man")
print(hamlet[loc:loc+100])
# sanity check a snippetAsk without context (hallucination test)
โถ๏ธ Create a new code cell and run it:
question = [{"role": "user", "content": "In Hamlet, when Laertes asks 'Where is my father?' what is the reply?"}]
response = completion(model="gemini/gemini-2.5-flash-lite", messages=question)
display(Markdown(response.choices[0].message.content))โ Model hallucinated a confident but wrong answer
Because no context attached = no accuracy
โถ๏ธ Create a new code cell and run it:
print(f"Input tokens: {response.usage.prompt_tokens}")
print(f"Output tokens: {response.usage.completion_tokens}")
print(f"Total tokens: {response.usage.total_tokens}")
print(f"Total cost: {response._hidden_params['response_cost']*100:.4f} cents")Inject full Hamlet as context
โถ๏ธ Create a new code cell and run it:
question[0]["content"] += "\n\nFor context, here is the entire text of Hamlet:\n\n" + hamletFirst call WITH context
โถ๏ธ Create a new code cell and run it:
response = completion(model="gemini/gemini-2.5-flash-lite", messages=question)
display(Markdown(response.choices[0].message.content))โ Correct answer because context attached: "Dead."
โถ๏ธ Create a new code cell and run it:
print(f"Input tokens: {response.usage.prompt_tokens}")
print(f"Output tokens: {response.usage.completion_tokens}")
print(f"Cached tokens: {response.usage.prompt_tokens_details.cached_tokens}")
print(f"Total cost: {response._hidden_params['response_cost']*100:.4f} cents")
Second identical call (cache kicks in)
โถ๏ธ Create a new code cell and run it:
response = completion(model="gemini/gemini-2.5-flash-lite", messages=question)
โถ๏ธ Create a new code cell and run it:
print(f"Input tokens: {response.usage.prompt_tokens}")
print(f"Output tokens: {response.usage.completion_tokens}")
print(f"Cached tokens: {response.usage.prompt_tokens_details.cached_tokens}")
print(f"Total cost: {response._hidden_params['response_cost']*100:.4f} cents")

๐ฐ ~5ร cheaper on the second call โ automatically, no code changes needed
๐ Token Cost Summary
Call | Input Tokens | Cached Tokens | Cost |
|---|---|---|---|
No context | ~19 | 0 | ~0.004ยข |
With context (1st) | ~53K | 0 | ~0.5ยข |
With context (2nd) | ~53K | ~44K | ~0.1ยข |
๐ The Golden Rule of Prompt Caching
โ ๏ธ Static content first, dynamic content last.
For caching to work, the beginning of your prompt must match between calls. As soon as the prefix differs, there's a cache miss.
โ
CORRECT: [Full Hamlet text] โ [Question about Hamlet]
โ WRONG: [Question] โ [Full Hamlet text]If you put today's date or the user's question at the top, every call will be a cache miss because the prefix changes every time.
๐ต OpenAI Prompt Caching
โ Fully automatic โ no code changes needed
๐ Only works on exact prefix matches โ the beginning of the prompt must be identical
๐ฐ Cached input tokens cost 4ร less
๐ผ๏ธ Applies to images and tools too โ they must also be identical between requests
๐ Anthropic Prompt Caching
โ๏ธ Manual โ you must explicitly tell Anthropic what to cache ("priming")
๐ธ Priming the cache costs 25% more upfront
๐ฐ But reusing from cache costs 10ร less โ a much bigger saving than OpenAI
๐งฎ Best for large, stable system prompts or documents used repeatedly
Trade-off summary:
OpenAI | Anthropic | |
|---|---|---|
Setup | Automatic | Manual (explicit) |
Cache prime cost | None | +25% |
Cache hit saving | 4ร cheaper | 10ร cheaper |
๐ข Gemini Prompt Caching โ Implicit vs Explicit
๐ Docs
Gemini supports both modes:
๐ Implicit Caching (automatic)
Works like OpenAI โ Gemini detects repeated prefixes and caches them automatically
No code changes required
What happened in the demo above โ Gemini cached Hamlet on the second call without any setup
๐ Explicit Caching (manual)
You proactively create a named cache object with the content you want stored
Gives you more control โ you can set a TTL (time-to-live), reuse across many sessions, and confirm it's cached before paying for calls
Similar philosophy to Anthropic's approach but with Gemini's API
When to use which:
Implicit | Explicit | |
|---|---|---|
Setup effort | None | Requires extra API calls |
Best for | Short sessions, quick experiments | Long-running apps, production systems |
Control | Low | High |