GEMINI LABJP
MODEL — Gemini 3.5 Flash is generally available as Google's top pick for agentic and coding tasksAGENT — Managed Agents enter public preview in the Gemini API, running in isolated Linux sandboxesWEBHOOK — Event-driven webhooks now cover the Batch API and long-running ops, removing pollingSECURITY — From June 19, requests from unrestricted API keys are blocked — review your key limitsDEPRECATED — Two image-preview models shut down June 25 — migrate any preview-dependent flowsCODEASSIST — Since June 18, individual Code Assist extensions and CLI stopped serving Pro/Ultra tiersMODEL — Gemini 3.5 Flash is generally available as Google's top pick for agentic and coding tasksAGENT — Managed Agents enter public preview in the Gemini API, running in isolated Linux sandboxesWEBHOOK — Event-driven webhooks now cover the Batch API and long-running ops, removing pollingSECURITY — From June 19, requests from unrestricted API keys are blocked — review your key limitsDEPRECATED — Two image-preview models shut down June 25 — migrate any preview-dependent flowsCODEASSIST — Since June 18, individual Code Assist extensions and CLI stopped serving Pro/Ultra tiers
Articles/Workspace
Workspace/2026-06-29Advanced

When Apps Script Time-Driven Triggers Quietly Run Out: Consolidating Gemini Automations into One Dispatcher

Apps Script caps you at 20 triggers per user and a daily total trigger-runtime budget. Here is how to stop your Gemini automations from silently dying as you add more, using a single dispatcher, a schedule table, and an external heartbeat.

gemini92apps-script8google-workspace6automation44trigger

Premium Article

"The auto-reply that worked yesterday had stopped — with no error at all." If you run several Google Workspace automations as an indie developer, you meet this silent failure sooner or later. In my own setup I was generating review-reply drafts for my wallpaper apps, summarizing inquiry emails, and rolling up sales figures — each on its own time-driven trigger. One day they all stopped together, and the execution log did not even record a failure.

The cause was not a bug in my code. I had exhausted Apps Script's trigger resources. We tend to design as if triggers are unlimited, but the ceiling arrives much earlier than expected. Below I pin that ceiling down in numbers, then show how to fold a sprawl of per-job triggers into a single dispatcher that fires every five minutes.

Triggers run dry against two separate limits

What most people miss is that there is more than one constraint. Exhaustion happens against two distinct resources.

The first is the number of triggers. Apps Script allows up to 20 triggers per user, per script. If you grow your automations as "one feature, one trigger," the 20th brings This script has too many triggers, and every ScriptApp.newTrigger after that fails quietly.

The second is the total trigger runtime per day. On a free gmail.com account, cumulative trigger runtime tops out around 90 minutes per day; even a paid Google Workspace account caps at roughly six hours. Because each Gemini API call spends seconds waiting on the network, that time budget melts faster than you would think as jobs pile up. Once it is gone, the rest of the day's triggers simply stop firing, with no notification.

The table below lists the key limits to keep in mind. Note that the numbers depend on the account type.

ResourceFree (gmail.com)Workspace (paid)Symptom on exhaustion
Triggers / user / script2020newTrigger fails
Total trigger runtime / day~90 min~6 hoursFiring stops silently
Max runtime per execution6 min30 minKilled mid-run
UrlFetch calls / day20,000100,000fetch throws

The point that bites is this: a trigger-per-feature design presses on both limits at once. It consumes trigger slots, and the startup overhead and empty checks of each trigger eat into the runtime budget. When mine stopped, I was still under 20 triggers — but three triggers firing every five minutes had drained the daily runtime budget before noon.

Drop one-trigger-per-job and consolidate into a single dispatcher

The skeleton of the fix is simple. Create exactly one trigger and fire it every five minutes. That single entry point decides, from a schedule table, which jobs are due, and runs only those in order. The trigger count stays at one, and so does the runtime footprint.

Start with the job definitions. Each job carries only an interval (in minutes) and the function to run.

// Job definitions. Each is just a declaration: run fn once every intervalMin.
const JOBS = [
  { id: 'reviewReplyDraft', intervalMin: 15, fn: runReviewReplyDraft },
  { id: 'inquirySummary',   intervalMin: 30, fn: runInquirySummary },
  { id: 'salesRollup',      intervalMin: 60, fn: runSalesRollup },
];
 
// The single entry point called by the 5-minute trigger
function dispatch() {
  const lock = LockService.getScriptLock();
  // Avoid overlap if the previous run is still going. Bow out silently if we can't get it.
  if (!lock.tryLock(1000)) return;
  try {
    const props = PropertiesService.getScriptProperties();
    const now = Date.now();
    const runStart = now;
    const RUN_BUDGET_MS = 4 * 60 * 1000; // Safety valve: exit before the 6-min cap
 
    for (const job of JOBS) {
      if (Date.now() - runStart > RUN_BUDGET_MS) break; // Respect the time budget
      const lastKey = 'last_' + job.id;
      const last = Number(props.getProperty(lastKey) || 0);
      if (now - last < job.intervalMin * 60 * 1000) continue; // Not due yet
      try {
        job.fn();
        props.setProperty(lastKey, String(now)); // Advance only on success
      } catch (e) {
        console.error('job failed: ' + job.id + ' / ' + e);
        // On failure, do not update last = it retries next cycle (each fn stays idempotent)
      }
    }
    props.setProperty('heartbeat', String(now)); // Liveness record
  } finally {
    lock.releaseLock();
  }
}

Three things matter here. First, RUN_BUDGET_MS makes the loop exit before hitting the six-minute execution cap; any leftover jobs are picked up by the next dispatch five minutes later. Second, LockService prevents double execution — if a previous run overruns into the next firing, one of them quietly steps aside, so the same job never runs in parallel. Third, last_ is advanced only on success; on failure the timestamp does not move, so the job retries on the next cycle.

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
You can now explain why triggers silently stop as you add Gemini automations, in terms of two concrete numbers: the 20-trigger cap and the ~90-minute daily runtime budget
You get working code that replaces one-trigger-per-job with a single 5-minute dispatcher driven by a schedule table
You can implement a heartbeat plus external monitoring and LockService double-run protection so a stalled pipeline never goes unnoticed
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

Workspace2026-04-09
Google Forms × Gemini API: Automated Response Analysis — Sentiment Analysis, Theme Extraction & Report Generation
Learn how to connect Google Forms with the Gemini API to automatically perform sentiment analysis, theme extraction, and report generation on survey responses. Includes complete Apps Script and Python implementation code you can deploy today.
Workspace2026-04-09
Google Looker Studio × Gemini API: Automate Business Report Analysis with AI
Connect Looker Studio with the Gemini API to auto-generate AI insights on reports. Includes Apps Script code, daily trigger setup, and troubleshooting tips.
Workspace2026-03-31
Building an AI Presentation Pipeline with Gemini API and Google Slides Apps Script — A
Learn how to build a complete presentation pipeline using Gemini API and Google Apps Script that auto-generates slide outlines, content, and designs from a single topic input.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links
See all →