GEMINI LABEN
MODEL — Gemini 3.5 Flashが一般提供。エージェント・コーディング向けの最有力モデルとして公開されましたAGENT — Managed AgentsがGemini APIで公開プレビュー。隔離されたLinuxサンドボックスで自律エージェントを実行できますWEBHOOK — Event-driven WebhooksがBatch APIと長時間処理に対応し、ポーリングが不要になりましたSECURITY — 6/19以降、未制限APIキーからのリクエストが遮断されます。キーの制限設定を見直しましょうDEPRECATED — 画像プレビュー2モデルが6/25で停止します。preview依存のフローは早めに移行をCODEASSIST — 6/18より個人向けCode Assist拡張とCLIが、AI Pro/Ultra層への提供を停止しましたMODEL — Gemini 3.5 Flashが一般提供。エージェント・コーディング向けの最有力モデルとして公開されましたAGENT — Managed AgentsがGemini APIで公開プレビュー。隔離されたLinuxサンドボックスで自律エージェントを実行できますWEBHOOK — Event-driven WebhooksがBatch APIと長時間処理に対応し、ポーリングが不要になりましたSECURITY — 6/19以降、未制限APIキーからのリクエストが遮断されます。キーの制限設定を見直しましょうDEPRECATED — 画像プレビュー2モデルが6/25で停止します。preview依存のフローは早めに移行をCODEASSIST — 6/18より個人向けCode Assist拡張とCLIが、AI Pro/Ultra層への提供を停止しました
記事一覧/Workspace 連携
Workspace 連携/2026-06-29上級

Apps Script の時間主導型トリガーが静かに枯渇する — Gemini 自動化を一本のディスパッチャに束ねる

Apps Script の時間主導型トリガーは1ユーザー20本・1日の合計実行時間にも上限があります。Gemini 自動化を増やすたびに無音で止まる問題を、単一ディスパッチャとスケジュール表とハートビートで解く実装を示します。

gemini92apps-script9google-workspace6automation32trigger

プレミアム記事

「昨日まで動いていた自動返信が、エラーも出ないまま止まっていた」。個人開発で複数の Google Workspace 自動化を運用していると、この無音の停止に何度か出くわします。私自身、壁紙アプリのレビュー返信の下書き生成と、問い合わせメールの要約と、売上シートの集計を、それぞれ別の時間主導型トリガーで回していた時期に、ある日まとめて止まりました。実行ログを開いても、失敗の記録すら残っていません。

原因はコードのバグではなく、Apps Script のトリガー資源を使い切っていたことでした。トリガーは無限に増やせる前提で設計しがちですが、実際にはかなり手前に天井があります。ここでは、その天井の正体を数字で押さえたうえで、ジョブごとにトリガーを乱立させる構成を、5分間隔の単一ディスパッチャに束ね直す実装を示します。

トリガーは「数」と「時間」の二重の上限で枯れる

多くの人が見落とすのは、トリガーの制約が一つではないことです。枯渇は別々の二つの資源で起こります。

ひとつは トリガーの本数 です。Apps Script では1ユーザーあたり1スクリプトに作成できるトリガーが20本までと決まっています。自動化を「1機能 = 1トリガー」で増やしていくと、20本目で This script has too many triggers が出て、それ以降の ScriptApp.newTrigger が静かに失敗します。

もうひとつは 1日あたりのトリガー合計実行時間 です。無料の gmail.com アカウントではトリガーの累積実行時間がおおむね1日90分、Google Workspace の有償アカウントでも6時間で頭打ちになります。Gemini API への呼び出しはネットワーク待ちで1回あたり数秒かかるため、ジョブが増えるとこの時間枠は思ったより速く溶けます。枠を使い切ると、その日の残りのトリガーは 通知もなく発火しなくなります

次の表は、運用設計で意識すべき主要な上限です。アカウント種別で数字が変わる点に注意してください。

資源無料(gmail.com)Workspace(有償)枯渇時の症状
トリガー本数 / ユーザー / スクリプト2020newTrigger が失敗
トリガー合計実行時間 / 日約90分約6時間発火が無音で停止
1実行あたりの最大時間6分30分途中で強制終了
UrlFetch 呼び出し / 日20,000100,000fetch が例外

ここで効いてくるのは、1機能ごとにトリガーを立てる設計が、両方の上限を同時に圧迫する という点です。本数を消費し、かつ各トリガーの起動オーバーヘッドと空振りチェックが実行時間枠を削ります。私が止まったときも、本数こそ20本未満でしたが、5分間隔のトリガーを3本回していたために、合計実行時間の枠を昼前に使い切っていました。

1機能=1トリガーをやめ、単一ディスパッチャに束ねる

解決の骨格はシンプルです。トリガーは ただ一本 だけ作り、それを5分おきに発火させます。その一本が「いまどのジョブを動かすべきか」をスケジュール表から判断し、期限の来たジョブだけを順に実行します。トリガーの本数は常に1、実行時間枠も1本ぶんに収まります。

まずジョブの定義です。各ジョブは「実行間隔(分)」と「実体の関数」を持つだけにします。

// ジョブ定義。intervalMin ごとに fn を1回走らせたい、という宣言だけを持つ
const JOBS = [
  { id: 'reviewReplyDraft', intervalMin: 15, fn: runReviewReplyDraft },
  { id: 'inquirySummary',   intervalMin: 30, fn: runInquirySummary },
  { id: 'salesRollup',      intervalMin: 60, fn: runSalesRollup },
];
 
// 5分間隔のトリガーから呼ばれる唯一の入口
function dispatch() {
  const lock = LockService.getScriptLock();
  // 前回の実行が長引いて重なるのを防ぐ。取れなければ今回は黙って降りる
  if (!lock.tryLock(1000)) return;
  try {
    const props = PropertiesService.getScriptProperties();
    const now = Date.now();
    const runStart = now;
    const RUN_BUDGET_MS = 4 * 60 * 1000; // 1実行6分の手前で必ず抜ける安全弁
 
    for (const job of JOBS) {
      if (Date.now() - runStart > RUN_BUDGET_MS) break; // 時間枠を守る
      const lastKey = 'last_' + job.id;
      const last = Number(props.getProperty(lastKey) || 0);
      if (now - last < job.intervalMin * 60 * 1000) continue; // まだ期限前
      try {
        job.fn();
        props.setProperty(lastKey, String(now)); // 成功時のみ前進
      } catch (e) {
        console.error('job failed: ' + job.id + ' / ' + e);
        // 失敗時は last を更新しない = 次回再試行される(冪等性は各 fn 側で担保)
      }
    }
    props.setProperty('heartbeat', String(now)); // 生存記録
  } finally {
    lock.releaseLock();
  }
}

ポイントは3つあります。ひとつ目は RUN_BUDGET_MS で、6分の実行上限に達する前に必ずループを抜けることです。残ったジョブは次の5分後のディスパッチで拾われます。ふたつ目は LockService による二重起動の防止で、前回が長引いて次の発火と重なっても、片方が静かに降りるので同じジョブが並行実行されません。みっつ目は、成功したときだけ last_ を更新することです。失敗時は時刻を進めないので、次の周回で自動的に再試行されます。

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

この記事の続きを読む

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

この記事で得られること
Gemini 自動化を増やすたびトリガーが無音で止まる原因を、20本上限と1日90分の実行時間枠という2つの数字で説明できるようになる
ジョブごとに別トリガーを立てる構成を、5分間隔の単一ディスパッチャとスケジュール表に置き換える動くコードを手に入れられる
止まったことに気づくためのハートビートと外部監視、LockService による二重起動防止まで含めた運用設計を実装できる
Stripe による安全な決済 · いつでもキャンセル可能

この記事を購入する

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

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

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

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

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

関連記事

Workspace 連携2026-06-16
Apps Script から Gemini でスプレッドシート数千行を処理する — 6分の実行上限を越える分割と冪等性の設計
Apps Script の6分実行上限でスプレッドシートのバッチ処理が途中で止まる問題を、トリガー継続・ステータス列による冪等処理・指数バックオフで最後まで流し切る設計と実装をまとめます。
Workspace 連携2026-04-09
Google Forms × Gemini API 回答自動分析システム構築ガイド:感情分析・テーマ抽出・レポート自動生成まで
Google FormsとGemini APIを連携し、アンケート回答を自動で感情分析・テーマ抽出・レポート化するシステムを実装まで具体的に解説します。Apps Script・Python実装コード付きで今日から導入できる実践ガイド。
Workspace 連携2026-04-09
Google Looker Studio × Gemini API でビジネスレポートをAI自動分析する
Google Looker Studio のデータを Gemini API で AI 分析する方法を徹底解説。Apps Script を使ったレポート自動化の手順、コード例、よくあるエラーまで網羅した実践ガイドです。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →