◉GEMINI LABEN
●ARGON — gemini-4-argon が 10/13 に GA。複雑なコーディング・エージェント・数学・科学向けです●DEEP RES — deep-research-pro-preview-12-2025 は 10/23 に停止、残り6日。移行先は deep-research-preview-04-2026●NANO — gemini-nano-banana-2.1 が GA(10/06)。gemini-3.1-flash-image は非推奨で停止日は未発表です●MCP — ツール結果が 8.5万トークンに膨らんだ事例を、ADK で 310 トークンに包んで抑えた報告が出ています●FLASH — gemini-3.7-flash と 3.5-flash は新しい Flash モデルに自動で回されます(10/08)●NEW — クラッシュ報告を毎回ゼロから読ませない — 既知バグ早見表を先に grep し…●ARGON — gemini-4-argon が 10/13 に GA。複雑なコーディング・エージェント・数学・科学向けです●DEEP RES — deep-research-pro-preview-12-2025 は 10/23 に停止、残り6日。移行先は deep-research-preview-04-2026●NANO — gemini-nano-banana-2.1 が GA(10/06)。gemini-3.1-flash-image は非推奨で停止日は未発表です●MCP — ツール結果が 8.5万トークンに膨らんだ事例を、ADK で 310 トークンに包んで抑えた報告が出ています●FLASH — gemini-3.7-flash と 3.5-flash は新しい Flash モデルに自動で回されます(10/08)●NEW — クラッシュ報告を毎回ゼロから読ませない — 既知バグ早見表を先に grep し…
記事一覧/API / SDK
◈ API / SDK/2026-07-08中級

有料チャットの Gemini 請求が見積りの倍になっていたとき — リクエスト単位でトークンを計上して原価の漏れを塞ぐ運用メモ

有料チャットSaaSの Gemini 請求が見積りの倍に膨らんだ実体験から、リクエスト単位でトークンを計上し、原価が漏れている箇所を特定して塞ぐ運用手順をまとめました。usage_metadata の記録と請求の突き合わせが起点です。

Gemini 2.5 Pro17Gemini API248コスト管理17usage_metadataSaaS運用

✦ プレミアム記事

月初に届いた Gemini の請求を開いて、しばらく画面を見つめていました。見積りの段階では月 $60 前後のはずでした。実際の数字は $128。倍近い。

利用者は想定どおりのペースで増えていました。単価表は何度も確認しました。それでも合わない。

原因は単価ではありませんでした。「1 リクエストがいくらか」を、私が実測ではなく紙の上の前提で信じていたことでした。個人開発で運営している小さな有料チャットだからこそ、この差は粗利を静かに削っていきます。

この記事は、その乖離をリクエスト単位のトークン計上で可視化し、原価が漏れている箇所を 3 つ見つけて塞いだときの記録です。

見積りが合わない、を数字で受け止める

最初にやったのは、感覚で語るのをやめることでした。

Gemini API のレスポンスには usageMetadata が含まれます。ここに promptTokenCount(入力)、candidatesTokenCount(出力)、cachedContentTokenCount(キャッシュヒット分)が入っています。これを毎リクエスト、必ず保存します。

// 全チャット応答でトークンを計上する薄いラッパ
async function generateWithAccounting({ model, contents, systemInstruction, userId, requestId }) {
  const res = await model.generateContent({ contents, systemInstruction });
  const u = res.response.usageMetadata ?? {};
 
  // 単価は 1M トークンあたりの USD(2026 年 7 月時点の Gemini 2.5 Pro)
  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;
}

ここで大事なのは、cachedContentTokenCount を入力から差し引いてから課金対象を計算している点です。キャッシュヒット分を通常入力単価で二重に数えると、今度は原価を過大に見積もってしまいます。

この token_ledger を一週間ためて、月次請求の日割りと突き合わせました。私の環境では記録合計と請求の差は 3% 以内。つまり台帳は信頼できる。ここからが本題です。

疑うべきは 3 系統だと当たりをつける

台帳が信頼できると分かった時点で、私自身の経験から当たりをつけました。見積りと請求がずれるとき、原因はたいてい単価の外側にある 3 系統に集約されます。ひとつは入力トークンの肥大、ふたつめはキャッシュの空振り、みっつめはリトライの二重課金です。

以降はこの 3 つを台帳で順に検証していきます。感覚で全部を疑うのではなく、計測できる仮説に絞ってから手を動かすのが、遠回りを避ける近道でした。

なお、usage_metadata の記録そのものの設計は Gemini API の使用量メタデータで原価を追跡する本番設計 に土台を書いています。本稿はその台帳を「乖離の犯人探し」に使う続きにあたります。

✦

ここまでお読みいただきありがとうございます。

この記事の続きを読む

この先には、実装コードやベンチマーク結果など、実務でお役に立てる内容をご用意しています。このサイトは広告を掲載しておらず、サーバーや開発にかかる費用はメンバーの皆様のご支援で成り立っています。もしお役に立てていましたら、ご支援いただけますと大変ありがたいです。

この記事で得られること
✦usage_metadata をリクエストごとに保存し、月次請求と 1 円単位で突き合わせる記録テーブルの設計
✦見積りとの乖離を「会話履歴の肥大」「キャッシュ書き込みの空振り」「リトライの二重課金」の 3 系統に切り分ける手順
✦原価が漏れる 3 系統をそれぞれ塞いだ後の、単価ではなく実効原価で粗利を守る運用の勘所
Stripe による安全な決済 · いつでもキャンセル可能
✦

この記事を購入する

この先の内容をすべてお読みいただけます。一度のご購入で、いつでも何度でもアクセスできます。このサイトは広告を掲載しておらず、皆さまのご支援がサーバー費用などの運営を支えています。

または
メンバーシップなら全記事が読み放題 →
シェア

お読みいただきありがとうございます

Gemini Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • ✦コピー&ペーストで使える実装コード付き
  • ✦毎日新しい上級ガイドを追加
  • ✦¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

関連記事

◈ API / SDK2026-09-08
値上げの日をまたぐ費用の見積もりを、はじめから二段で書く
Gemini Flash の導入価格は2026年12月31日で終わり、2027年1月1日から標準価格に切り替わります。世代を据え置いても避けられないこの日を、はじめての費用見積もりでどう扱うか。動くコードとともに書き残します。
◈ API / SDK2026-10-14
config に「Extra inputs are not permitted」が出たら、キーの綴りを一つずつ疑います
google-genai SDK で config を渡した途端に pydantic の ValidationError(extra_forbidden)が出る原因は、ほぼ綴りの一字違いです。手元で再現した出力と、呼び出し前に怪しいキーを洗う関数、text が None になる場合の見分け方を書き残します。
◈ API / SDK2026-10-08
停止日のない非推奨をどう扱うか — 画像モデルの移行先を、3つの条件で選び直す
10月6日に gemini-nano-banana-2.1 が GA になり、gemini-3.1-flash-image は停止日の書かれないまま非推奨になりました。解像度・参照画像・検索の3条件で移行先を選ぶ表と、確認用の短いスクリプトをまとめます。