◉GEMINI LABEN
●ARGON — gemini-4-argon が 10/13 に GA。複雑なコーディング・エージェント・数学・科学向けです●DEEP RES — 旧 Deep Research エージェントは 10/23 に停止済み。呼び出しが失敗する場合は deep-research-preview-04-2026 へ●NANO — gemini-nano-banana-2.1 が GA(10/06)。gemini-3.1-flash-image は非推奨で停止日は未発表です●CLI — Gemini API CLI(gemini-api)がベータで登場(10/27)。エージェントやCI向けのゼロ依存クライアントです●STORE — 新規の有料プロジェクトでは生成リクエストの保存(store)が既定でオンになります(10/26)●NEW — クラッシュ報告を毎回ゼロから読ませない — 既知バグ早見表を先に grep し…●ARGON — gemini-4-argon が 10/13 に GA。複雑なコーディング・エージェント・数学・科学向けです●DEEP RES — 旧 Deep Research エージェントは 10/23 に停止済み。呼び出しが失敗する場合は deep-research-preview-04-2026 へ●NANO — gemini-nano-banana-2.1 が GA(10/06)。gemini-3.1-flash-image は非推奨で停止日は未発表です●CLI — Gemini API CLI(gemini-api)がベータで登場(10/27)。エージェントやCI向けのゼロ依存クライアントです●STORE — 新規の有料プロジェクトでは生成リクエストの保存(store)が既定でオンになります(10/26)●NEW — クラッシュ報告を毎回ゼロから読ませない — 既知バグ早見表を先に grep し…
記事一覧/API / SDK
◈ API / SDK/2026-06-12上級

深夜のポーリングをやめる — Gemini Batch API を Webhook 駆動に作り替えた設計記録

Gemini Batch API の完了監視を 60 秒間隔のポーリングから Webhook 駆動へ移行した実作業の記録です。static/dynamic の使い分け、署名検証、実測値をまとめました。

Gemini API251Batch API5Webhook3イベント駆動運用設計15Python52

✦ プレミアム記事

明け方 4 時のサーバーログを眺めていて、手が止まりました。

夜間に流している Gemini Batch API のジョブはとっくに終わっているのに、結果の取り込みが始まったのは 58 秒後。理由は単純で、完了確認のポーリングが 60 秒間隔だったからです。

ログの大半は「まだ終わっていません」という応答の記録でした。一晩分をざっと数えると、status 確認の GET だけで 1,000 回を超えています。仕事をしていない通信が、ログの約 90% を占めている状態。

2026 年 5 月に Gemini API へ Webhooks が正式に入ったのを機に、この監視層を作り替えることにしました。本稿はその実作業の記録です。

ポーリング監視の実測コスト

作り替えの前に、現状を数字で押さえておきます。私の夜間パイプラインは、個人開発しているアプリの App Store・Google Play 向け説明文と、アプリ内テキストの多言語ローカライズ文言を Batch API でまとめて生成するもので、毎晩 3 ジョブを流しております。

  • ポーリング間隔: 60 秒
  • 1 ジョブの平均所要時間: 約 2 時間(Batch API はベストエフォートのため夜によって大きく揺れます)
  • 一晩の GET 回数: 約 120 回 × 3 ジョブ × リトライ込みで 約 1,080 回
  • 完了から検知までの遅延: 平均 30 秒、最悪 60 秒

GET 自体は無料に近いとはいえ、cron とポーリングスクリプトという「動き続ける部品」を一つ抱えることになります。実際、過去にはポーリング側の例外処理の不備で監視だけが静かに死んでいた朝がありました。ジョブは成功しているのに結果が取り込まれていない。あの空振りの感覚は、いまも指先に残っております。

static と dynamic、どちらで受けるか

Gemini API の Webhook には 2 種類あります。最初にここの設計判断を誤ると後で作り直しになるため、丁寧に整理します。

static webhook はプロジェクト単位の登録です。webhooks.create で一度エンドポイントを登録すると、購読したイベント(batch.succeeded や batch.failed など)がプロジェクト全体から飛んできます。署名は対称鍵(signing secret)の HMAC 方式。

dynamic webhook はジョブ単位の指定です。batches.create の webhook_config に URI を渡すと、そのジョブの完了通知だけが届きます。署名は JWKS による非対称鍵方式で、user_metadata に任意のルーティング情報を載せられます。

私の環境では次のルールに落ち着きました。

  1. 定常の夜間バッチ → static。エンドポイントが固定で、Slack 通知やデータベース更新のような「全ジョブ共通の後処理」に繋がるため
  2. 臨時・実験ジョブ → dynamic。user_metadata に {"job_group": "experiment"} のような目印を載せ、本番の後処理に混ざらないよう専用エンドポイントで受けるため

逆にしないことが肝心だと感じております。臨時ジョブのために static の購読を増やすと、レシーバー側の分岐が際限なく育ちます。

✦

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

この記事の続きを読む

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

この記事で得られること
✦一晩あたり約 1,080 回あった status 確認の GET をゼロにした移行手順と、移行後も薄いフォールバックポーリングを残した判断基準
✦static webhook と dynamic webhook をジョブの性質でどう使い分けるか — 私の環境で固まった具体的な振り分けルール
✦standardwebhooks ライブラリによる署名検証・5 分の replay 対策・webhook-id での重複排除まで含めた、そのまま動く Flask レシーバーの実装
Stripe による安全な決済 · いつでもキャンセル可能
✦

この記事を購入する

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

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

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

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

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

関連記事

◈ 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条件で移行先を選ぶ表と、確認用の短いスクリプトをまとめます。
◈ API / SDK2026-09-22
関数呼び出しが平文に化けるとき、まず疑うのはツール宣言のプロパティ名です
MALFORMED_FUNCTION_CALL を出力上限とスキーマ衝突で潰しきれなかったとき、ツール宣言のプロパティ名を二分探索で絞り込んだ記録です。予約語を名前に置かない線引きと、宣言の手前で落とすリンタまで書き残します。