IntentiAI

Gemini context cache created and never deleted

Provider-side caches created and never deleted, billed by the hour.

Rule cache-storage-leakCost audit

Why it costs money

Gemini's explicit context caching has two prices: a reduced rate for cached input tokens, and an hourly storage fee for every token in the cache for as long as it lives. Storage is charged whether the cache is read a hundred times or never.

A cache that is created and left to expire, or created fresh for every request, pays storage for its whole time to live. As an example, a 200,000-token cache with a 24-hour TTL is 4.8 million token-hours of storage, even if it served one question. Because this fee is separate from per-call usage, it is easy to miss in a spend dashboard.

Example

Flagged

from google import genai
from google.genai import types

client = genai.Client()
MODEL = "gemini-2.5-pro"


def answer_about_contract(contract_text: str, question: str) -> str:
    cache = client.caches.create(
        model=MODEL,
        config=types.CreateCachedContentConfig(contents=[contract_text], ttl="86400s"),
    )
    response = client.models.generate_content(
        model=MODEL,
        contents=question,
        config=types.GenerateContentConfig(cached_content=cache.name),
    )
    return response.text

Fixed

from google import genai
from google.genai import types

client = genai.Client()
MODEL = "gemini-2.5-pro"


def review_contract(contract_text: str, questions: list[str]) -> list[str]:
    cache = client.caches.create(
        model=MODEL,
        config=types.CreateCachedContentConfig(contents=[contract_text], ttl="600s"),
    )
    try:
        return [
            client.models.generate_content(
                model=MODEL,
                contents=q,
                config=types.GenerateContentConfig(cached_content=cache.name),
            ).text
            for q in questions
        ]
    finally:
        client.caches.delete(name=cache.name)

How to fix it

Create a cache once for content that will be reused, use it for every request that needs it, and delete it as soon as that work is done, ideally in a finally block. Set a short, explicit TTL that matches the real reuse window as a backstop.

If the cache must outlive one function, key it by a hash of the content so repeated requests reuse the same cache, and run a periodic cleanup that deletes caches your app no longer references.

What the audit detects

  • Explicit Gemini cache creation in code (caches.create, create_cached_content, createCachedContent, CachedContent.create). Comments and docstrings are ignored.
  • If no cache delete call (caches.delete, cachedContents.delete and equivalents) exists anywhere in the repo, it reports an orphaned cache.
  • A create call inside a loop or request handler is reported separately, since a new cache per request pays write and storage with little reuse.
  • When deletes do exist, a create with no TTL or expire time nearby gets a lower-severity note. Implicit (automatic) caching is out of scope.

Research

Gemini API docs: Context caching. Explicit caches are billed an hourly storage fee for the whole TTL in addition to token usage, so a cache that is never deleted keeps costing money even when it is never read.

Gemini context cache created and never deleted: LLM cost rule | IntentiAI