◉GEMINI LABJP
●ARGON — gemini-4-argon is generally available as of 10/13, aimed at complex coding, agents, math and science●DEEP RES — deep-research-pro-preview-12-2025 shuts down 10/23, 6 days left. Move to deep-research-preview-04-2026●NANO — gemini-nano-banana-2.1 is GA (10/06). gemini-3.1-flash-image is deprecated with no shutdown date yet●MCP — One write-up cut an 85,000-token tool result to 310 tokens by wrapping it in an ADK FunctionTool●FLASH — gemini-3.7-flash and 3.5-flash now route automatically to newer Flash models (10/08)●NEW — Stop Re-Reading Every Crash Report: Gre…●ARGON — gemini-4-argon is generally available as of 10/13, aimed at complex coding, agents, math and science●DEEP RES — deep-research-pro-preview-12-2025 shuts down 10/23, 6 days left. Move to deep-research-preview-04-2026●NANO — gemini-nano-banana-2.1 is GA (10/06). gemini-3.1-flash-image is deprecated with no shutdown date yet●MCP — One write-up cut an 85,000-token tool result to 310 tokens by wrapping it in an ADK FunctionTool●FLASH — gemini-3.7-flash and 3.5-flash now route automatically to newer Flash models (10/08)●NEW — Stop Re-Reading Every Crash Report: Gre…
Articles/API / SDK
◈ API / SDK/2026-07-08Intermediate

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.

Gemini 2.5 Pro17Gemini API249cost management4usage_metadataSaaS operations

✦ Premium Article

I opened the Gemini invoice on the first of the month and just stared at it for a while. My estimate had put it around $60. The actual number was $128. Nearly double.

Usage had grown exactly as expected. I checked the price table several times. Still it did not add up.

The culprit was not the unit price. It was that I had trusted my paper assumption of "what one request costs" instead of measuring it. When you run a small paid chat service as an indie developer, that gap quietly eats your margin.

This is a record of making that gap visible through per-request token accounting, finding three places where cost was leaking, and plugging them.

Face the gap with numbers, not feelings

The first thing I did was stop reasoning by intuition.

Every Gemini API response includes usageMetadata, carrying promptTokenCount (input), candidatesTokenCount (output), and cachedContentTokenCount (the cache-hit portion). I now save all of it, on every request, without exception.

// A thin wrapper that accounts for tokens on every chat response
async function generateWithAccounting({ model, contents, systemInstruction, userId, requestId }) {
  const res = await model.generateContent({ contents, systemInstruction });
  const u = res.response.usageMetadata ?? {};
 
  // Rates are USD per 1M tokens (Gemini 2.5 Pro as of July 2026)
  const RATE = { input: 1.5, output: 6.0, cacheHit: 0.375, cacheWrite: 2.25 };
  const cached = u.cachedContentTokenCount ?? 0;
  const inputBillable = (u.promptTokenCount ?? 0) - cached;
  const costUsd =
    (inputBillable / 1e6) * RATE.input +
    (cached / 1e6) * RATE.cacheHit +
    ((u.candidatesTokenCount ?? 0) / 1e6) * RATE.output;
 
  await db.insert('token_ledger', {
    request_id: requestId,
    user_id: userId,
    prompt_tokens: u.promptTokenCount ?? 0,
    cached_tokens: cached,
    output_tokens: u.candidatesTokenCount ?? 0,
    est_cost_usd: costUsd,
    created_at: new Date(),
  });
  return res;
}

The important detail is subtracting cachedContentTokenCount from input before computing the billable amount. If you count the cache-hit portion at the full input rate, you swing the other way and overstate your cost.

I let this token_ledger accumulate for a week and reconciled it against the pro-rated monthly invoice. In my environment the ledger total and the invoice differed by under 3%. So the ledger was trustworthy. That is where the real work began.

Bet that the culprit is one of three lanes

Once I knew the ledger was trustworthy, I made a bet from my own experience as an indie developer. When the estimate and the invoice diverge, the cause almost always collapses into three lanes outside the unit price: input-token bloat, cache misses, and retry double-billing.

From here I verify each of the three in the ledger, in order. Rather than suspecting everything by feel, narrowing to measurable hypotheses before touching code was the shortest way to avoid a detour.

The design of recording usage_metadata itself is covered in Tracking cost with Gemini API usage metadata in production. This piece is the sequel that turns that ledger into a hunt for the leak.

✦

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 token_ledger design that records usage_metadata per request and reconciles it against the monthly invoice to the cent
✦A procedure that splits the gap from the estimate into three lanes: conversation-history bloat, cache writes that never get read, and retry double-billing
✦How to protect margin using effective cost per request rather than the unit price table, after each leak is plugged
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-09-08
Writing my first Gemini cost estimate in two columns, one for now and one for January
Introductory pricing for Gemini Flash ends on December 31, 2026, and standard pricing starts on January 1, 2027. Staying on an older generation does not avoid it. Here is the small, working estimator I use to see both prices at once.
◈ API / SDK2026-10-14
When Your config Raises "Extra inputs are not permitted", Check the Spelling of Every Key
If a google-genai call fails with a pydantic ValidationError (extra_forbidden) the moment you pass a config, it is almost always a one-letter typo. Here is the output I reproduced, a small function that checks keys before the call, and how to tell why response.text came back as None.
◈ API / SDK2026-10-08
When a Deprecation Has No Shutdown Date: Re-Picking an Image Model on Three Conditions
gemini-nano-banana-2.1 went GA on October 6, and gemini-3.1-flash-image was deprecated with no shutdown date. Here is a table and a short script for choosing a replacement by resolution, reference images, and search grounding.