GEMINI LABEN
REGION — Gemini Enterprise app の global リージョンから Gemini 3.5 Flash が本日除去されます。リージョン指定を明示していない構成ほど、選択肢が黙って変わる形で表面化しますIMAGE — Imagen 4 系と Gemini 3 Image 系の画像生成モデルが8月17日に停止します。移行の猶予は残り2週間ですROBOTICS — gemini-robotics-er-1.6-preview は8月31日に停止します。プレビュー系は代替経路を用意しておく前提で扱うのが現実的ですSAMPLING — Gemini 3.6 Flash では temperature・top-K・top-P のカスタム値が無視され、frequency penalty と presence penalty は API エラーになりますFLASH — Gemini 3.6 Flash と 3.5 Flash-Lite が一般提供に移りました。3.6 Flash はトークン効率と計画能力が改善し、3.5 Flash より低価格ですAGENTS — Gemini API の Managed Agents に 3.6 Flash と hooks が加わり、エージェントの実行途中に処理を挟む設計が公式にサポートされましたREGION — Gemini Enterprise app の global リージョンから Gemini 3.5 Flash が本日除去されます。リージョン指定を明示していない構成ほど、選択肢が黙って変わる形で表面化しますIMAGE — Imagen 4 系と Gemini 3 Image 系の画像生成モデルが8月17日に停止します。移行の猶予は残り2週間ですROBOTICS — gemini-robotics-er-1.6-preview は8月31日に停止します。プレビュー系は代替経路を用意しておく前提で扱うのが現実的ですSAMPLING — Gemini 3.6 Flash では temperature・top-K・top-P のカスタム値が無視され、frequency penalty と presence penalty は API エラーになりますFLASH — Gemini 3.6 Flash と 3.5 Flash-Lite が一般提供に移りました。3.6 Flash はトークン効率と計画能力が改善し、3.5 Flash より低価格ですAGENTS — Gemini API の Managed Agents に 3.6 Flash と hooks が加わり、エージェントの実行途中に処理を挟む設計が公式にサポートされました
記事一覧/API / SDK
API / SDK/2026-08-04上級

停止済みモデルの再試行は、成功レイテンシには出ませんでした

画像生成モデルの停止日が近づいています。停止済みモデルを呼んだときリトライ層が何をするのかを、モックサーバーで再現して計測しました。壊れ方は所要時間と待ち行列に出て、成功レイテンシには出ませんでした。

Gemini API202エラーハンドリング2リトライ設計3モデル移行8可観測性3

プレミアム記事

8月4日、Gemini Enterprise アプリの global リージョンのモデル一覧から Gemini 3.5 Flash が外れる日でした。8月17日には旧来の画像生成モデルが停止します。手元の設定ファイルを開いて、モデル ID が何箇所に散っているかを数えたところで、手が止まりました。

数えるべきはそこではありませんでした。

停止日を過ぎたあと、自分のコードがどう壊れるかを、私は説明できませんでした。呼び出しが失敗することは分かります。ただ、その失敗をリトライ層がどう扱い、バッチ全体がどうなるのかは、想像の域を出ていませんでした。

想像で移行計画を立てるのは落ち着かないので、手元で再現して測ることにしました。

恒久エラーと一時エラーを、同じ箱に入れていました

個人開発で回している定期バッチのリトライ層を読み返して、すぐに気づいたことがあります。

失敗したら指数バックオフで4回まで再試行する。それだけでした。何が失敗したのかは見ていません。

この作りは、過負荷(503 UNAVAILABLE)やレート超過(429 RESOURCE_EXHAUSTED)に対しては正しく働きます。時間を置けば直る種類のエラーだからです。

停止したモデルは、時間を置いても直りません。3.5 秒待ってもう一度呼んでも、返ってくるのは同じ 404 NOT_FOUND です。

つまり移行漏れが1件あるたびに、私のバッチは確実に失敗すると分かっている呼び出しを4回投げ、その間に 3.5 秒眠ることになります。

問題はここからです。それがどれくらいの実害になるのか、私には見当がつきませんでした。「多少遅くなる」で済むのか、それとも致命的なのか。

計測ハーネス: 停止済みモデルの応答を手元で再現する

実 API に停止済みモデルを叩き続けるわけにはいきませんので、公式ドキュメントに記載されているエラー形(停止済みモデルは 404 NOT_FOUND、過負荷は 503 UNAVAILABLE)を返すモックサーバーを立てました。

停止済みモデル ID を叩いたら必ず 404、生きているモデルは 6% の確率で 503、残りは 40ms の生成レイテンシを模して 200 を返します。

# server.py — 停止済みモデルの応答を手元で再現するモック
import json, random, threading, time
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
 
RETIRED = {"imagen-4.0-generate-001", "gemini-3-image-preview"}
AVAILABLE = {"gemini-3.6-flash", "nano-banana-2-lite"}
rng = random.Random(20260804)   # 再現性のため固定シード
COUNT = {"total": 0, "retired": 0, "transient": 0, "ok": 0}
LOCK = threading.Lock()
 
class H(BaseHTTPRequestHandler):
    protocol_version = "HTTP/1.1"   # keep-alive。これを外すと計測がTCP接続コストに支配されます
    def log_message(self, *a): pass
 
    def do_POST(self):
        n = int(self.headers.get("content-length", 0))
        model = json.loads(self.rfile.read(n) or b"{}").get("model", "")
        with LOCK:
            COUNT["total"] += 1
 
        if model in RETIRED:
            with LOCK:
                COUNT["retired"] += 1
            self._send(404, {"error": {"code": 404, "status": "NOT_FOUND",
                "message": f"models/{model} is not found or no longer supported."}})
            return
 
        if rng.random() < 0.06:      # 一時的な過負荷
            with LOCK:
                COUNT["transient"] += 1
            self._send(503, {"error": {"code": 503, "status": "UNAVAILABLE",
                "message": "The model is overloaded. Please try again later."}})
            return
 
        time.sleep(0.04)             # 生成レイテンシの模擬
        with LOCK:
            COUNT["ok"] += 1
        self._send(200, {"model": model, "output": "ok"})
 
    def do_GET(self):
        if self.path == "/models":
            self._send(200, {"models": [{"name": f"models/{m}"} for m in sorted(AVAILABLE)]})
        else:
            self._send(404, {"error": {"code": 404, "status": "NOT_FOUND"}})
 
    def _send(self, code, obj):
        b = json.dumps(obj).encode()
        self.send_response(code)
        self.send_header("content-type", "application/json")
        self.send_header("content-length", str(len(b)))
        self.end_headers()
        self.wfile.write(b)
 
ThreadingHTTPServer(("127.0.0.1", 8931), H).serve_forever()

protocol_version を HTTP/1.1 に上げている点だけ補足させてください。既定の HTTP/1.0 のままだと毎回 TCP 接続が張り直され、計測したい差分が接続コストに埋もれます。最初の試行でこれに気づかず、3クライアントの差がほとんど出ずに首をかしげました。

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

この記事の続きを読む

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

この記事で得られること
恒久エラーを再試行する実装が、バッチ全体の所要時間を 1.56 秒から 8.36 秒へ伸ばした実測(同一条件・3回の中央値)
壊れ方が現れる指標: 成功レイテンシ p95 ではなく、投入から実行開始までの待ち時間 p95(759ms → 4,682ms)
停止済みモデル ID を境界の1箇所で落とす preflight 実装と、それを速度目的で置いてはいけない理由
Stripe による安全な決済 · いつでもキャンセル可能

この記事を購入する

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

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

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

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

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

関連記事

API / SDK2026-06-21
Gemini API モデル非推奨・移行エラーの対処法
Gemini API でモデルが非推奨になった時の移行手順と、移行時に発生するエラーの対処法を詳しく解説します。
API / SDK2026-06-11
Gemini 3.2 API 実装ガイド — 正しいモデルID・3.1 からの移行と本番チェックポイント
Gemini 3.2 を API から呼び出すための正しいモデルID、Gemini 3.1 からの移行時の変更点、Python・TypeScript の実装例、本番環境への移行チェックリストをまとめました。
API / SDK2026-08-03
Memory profiles の更新ポリシーを測って選ぶ — 確定値を守るガードが精度を16ポイント下げた記録
Memory Bank の Memory profiles が GA になり、構造化された記憶を後段へ渡せるようになりました。更新ポリシーを3種類つくって同条件で比較したところ、直感的に正しく見えた防御が精度を下げていました。計測コード一式と、フィールド別TTLへ切り替えるまでの記録です。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →