GEMINI LABJP
PRO35 — July 17, the date reports had pointed to, has passed without an official Gemini 3.5 Pro announcement or model card. July 24 is being cited as the fallbackNB2LITE — Nano Banana 2 Lite, otherwise known as Gemini 3.1 Flash-Lite Image, arrives as the fastest of the family: roughly four seconds per image at $0.034 per thousandOMNI — Gemini Omni Flash enters public preview, generating video up to ten seconds long at $0.10 per second of outputEDIT — Omni Flash is built around conversational editing. Swap a character, relight a scene, or change the angle in plain language, and the original audio and video tracks stay intactSYNTHID — Both new models carry SynthID watermarking, so anything they produce can be checked for provenance from inside the Gemini appSHUTDOWN — The older image generation models are deprecated and switch off on August 17. Worth checking your migration windowPRO35 — July 17, the date reports had pointed to, has passed without an official Gemini 3.5 Pro announcement or model card. July 24 is being cited as the fallbackNB2LITE — Nano Banana 2 Lite, otherwise known as Gemini 3.1 Flash-Lite Image, arrives as the fastest of the family: roughly four seconds per image at $0.034 per thousandOMNI — Gemini Omni Flash enters public preview, generating video up to ten seconds long at $0.10 per second of outputEDIT — Omni Flash is built around conversational editing. Swap a character, relight a scene, or change the angle in plain language, and the original audio and video tracks stay intactSYNTHID — Both new models carry SynthID watermarking, so anything they produce can be checked for provenance from inside the Gemini appSHUTDOWN — The older image generation models are deprecated and switch off on August 17. Worth checking your migration window
Articles/API / SDK
API / SDK/2026-07-06Advanced

When Context Caching Didn't Lower My Gemini Bill — Field Notes on Measuring the Real Hit Rate

When Context Caching is enabled but the Gemini API bill barely drops, this field note measures the real hit rate from usage_metadata, separates TTL churn from fragmentation, and walks through a staged recovery.

Gemini API190Context Caching4cost optimization8usage_metadata2TTLinstrumentation3operations10

Premium Article

Only the invoice said it wasn't working

I turned on Context Caching because my system prompt had grown to 8,000 tokens and the input charges were no longer something I could ignore. As an indie developer running a micro-SaaS, every unit of cost feeds straight into the gross margin. I built the explicit cache exactly as documented, switched to passing cached_content, and waited two weeks. Then I opened the first invoice of the month and my finger stopped on the trackpad.

The input charges had barely moved. I had expected roughly a 60% drop; the reality was closer to 10%. The code looked correct. No errors. And yet the numbers were quietly insisting that nothing was working.

In moments like this, I stop suspecting the code first. What I suspect is my own assumption that "it must be working." Whether a cache actually took effect is never a feeling — it is written into the response metadata. So the recovery began by building a meter to read exactly that.

Confirming "it must be working" from the response

Every Gemini API response carries usage_metadata. Inside it is a field called cached_content_token_count, which tells you how many tokens of that request's prompt were served from the cache. If it reads 0, the cache did nothing — no matter how correct the implementation looks.

I started with the smallest possible check, printing the breakdown of a single request.

from google import genai
from google.genai import types
 
client = genai.Client(api_key="YOUR_API_KEY")
 
# Cache ONLY the fixed part shared by all users
cache = client.caches.create(
    model="gemini-2.5-flash",
    config=types.CreateCachedContentConfig(
        system_instruction=SYSTEM_PROMPT,  # the 8,000-token shared instruction
        ttl="3600s",
    ),
)
 
resp = client.models.generate_content(
    model="gemini-2.5-flash",
    contents=user_message,                 # only the per-user part
    config=types.GenerateContentConfig(cached_content=cache.name),
)
 
u = resp.usage_metadata
print("prompt:", u.prompt_token_count)
print("cached:", u.cached_content_token_count)  # this is the real signal
print("output:", u.candidates_token_count)

In my environment, some requests returned the expected cached value of around 8,000 — and others, inexplicably, returned 0. "Usually working, but sometimes not." That "sometimes" was piling up into a 10% invoice reduction. If you only watch the average, this flicker stays invisible.

Thank you for reading this far.

Continue Reading

What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.

WHAT YOU'LL LEARN
A tiny meter built on usage_metadata.cached_content_token_count to measure the effective hit rate
The break-even math: how many hits inside one TTL window make caching profitable
Separating the three silent causes: TTL churn, per-user fragmentation, and leaning on implicit caching
Secure payment via Stripe · Cancel anytime

Unlock This Article

Get full access to the rest of this article. Buy once, read anytime. This site is ad-free — your support goes directly toward keeping it running.

or
Unlock all articles with Membership →
Share

Thank You for Reading

Gemini Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $10 for lifetime access
View Membership →

Related Articles

API / SDK2026-04-02
How I Cut My Gemini API Bill from ¥52,000 to ¥8,400 a Month — Caching, Model Routing, and the Batch API
A working record of cutting my Gemini API bill from ¥52,000 to ¥8,400 a month. Covers implicit vs. explicit caching, Flash/Pro routing rules, migrating to the Batch API, and a usage_metadata logging setup — with the production code I actually run.
API / SDK2026-07-11
When Gemini's Context Cache Quietly Expires Mid-Run: A TTL Guard for Pipelines That Pause
When a nightly batch or a retry backoff pauses your pipeline, Gemini's explicit context cache can expire on the wall clock while nothing errors out, sending later calls back to full-token billing. Here is a small lease guard that decides whether to re-arm or run uncached based on cost.
API / SDK2026-07-08
When My Paid Gemini Chat Bill Came in at Double the Estimate — Field Notes on Per-Request Token Accounting to Plug the Cost Leaks
From a real overrun where my paid Gemini chat SaaS bill nearly doubled the estimate, here is how I logged token usage per request, traced where cost was leaking, and plugged three specific gaps. Recording usage_metadata and reconciling it against the invoice is the starting point.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links
See all →