GEMINI LABJP
SPARK — Gemini Spark, Google's agentic assistant, arrives in the Gemini app for macOS and works on tasks on your behalfBRIEF — Daily Brief, powered by Personal Intelligence, distills priorities from Gmail and Calendar with suggested next stepsMODEL — Gemini 3.5 Flash reaches GA, offering faster, lower-cost AI with a 1M-token context windowGROWTH — The Gemini app has passed 900 million monthly active users, up from 400 million a year earlierAPPS — Spark now connects to Google Tasks and Google Keep and stays up to date on topics in real timeENTERPRISE — Gemini 3.5 Flash is generally available across the Global, US, and EU regions on Gemini EnterpriseSPARK — Gemini Spark, Google's agentic assistant, arrives in the Gemini app for macOS and works on tasks on your behalfBRIEF — Daily Brief, powered by Personal Intelligence, distills priorities from Gmail and Calendar with suggested next stepsMODEL — Gemini 3.5 Flash reaches GA, offering faster, lower-cost AI with a 1M-token context windowGROWTH — The Gemini app has passed 900 million monthly active users, up from 400 million a year earlierAPPS — Spark now connects to Google Tasks and Google Keep and stays up to date on topics in real timeENTERPRISE — Gemini 3.5 Flash is generally available across the Global, US, and EU regions on Gemini Enterprise
Articles/Workspace
Workspace/2026-07-08Advanced

Your Apps Script Gemini Automation Fails Every Month-End — Budgeting Against the UrlFetch Daily Quota

Apps Script automations that call Gemini stall on the UrlFetch daily call quota — a separate ceiling from the 6-minute limit and trigger counts. Here is a daily budget governor with backlog carry-over that keeps the job running on busy days, with working code and a verified simulation.

Apps Script5Gemini API175UrlFetchAppGoogle Workspace14automation50

Premium Article

Every month-end, the same automation quietly died.

As an indie developer I run a handful of apps on my own, and a few of them lean on Apps Script to call Gemini — drafting replies to user reviews, tagging newly added wallpapers. On ordinary days everything flows without a hitch. But on a few days each month, an unfamiliar error showed up in the execution log, always the day after reviews had surged.

My first guess was rate limiting (429). But a 429 should be absorbed by exponential backoff. Following the log, I found the failure was not on Gemini's side at all — it was on Apps Script's. Service invoked too many times for one day: urlfetch. I had hit the UrlFetch daily call quota.

This article focuses on that third ceiling: the daily call quota of UrlFetchApp, which is neither the 6-minute runtime limit nor the trigger-count limit. It stays invisible while volume is steady and only shows its teeth on busy days. I will lay out a design that absorbs it quietly — a daily budget governor plus backlog carry-over — with working code and a verified simulation.

The third ceiling is "how many times can you call UrlFetch in a day"

As an Apps Script Gemini automation grows, it hits separate limits in sequence. Runtime and triggers are the well-known ones; the UrlFetch daily quota tends to hide behind them.

Limit you hitWhat is cappedconsumer (gmail.com)Google Workspace
Execution timeLongest single execution6 min / execution30 min / execution
Total trigger runtimeTrigger runtime per day90 min / day6 hr / day
UrlFetch daily callsUrlFetch calls per day20,000 / day100,000 / day

The runtime wall can be crossed by splitting work and continuing in the next trigger. The trigger-count wall can be crossed by consolidating into a single dispatcher. But the UrlFetch daily quota is different in kind: splitting or consolidating does not change the total number of calls you can issue in one day. If your design calls Gemini once per item, the number of items you process that day maps directly onto the quota.

I covered the runtime and trigger bottlenecks in earlier articles. This one is about the problem that remains even after you have solved both — how many calls you can make in a day. For the related designs, see crossing the 6-minute limit with chunking and idempotency and consolidating time-driven triggers into one dispatcher; together they make clear that the three ceilings are genuinely separate.

The naive version melts the quota on a busy day

Here is the naive version I wrote first. On each trigger, pick up every unprocessed row and send it to Gemini — on ordinary days, that is enough.

// Before: process all pending each run (fails on busy days)
function enrichPendingRows() {
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('reviews');
  const rows = sheet.getDataRange().getValues();
 
  for (let i = 1; i < rows.length; i++) {
    if (rows[i][STATUS_COL]) continue;      // skip done rows
    const draft = callGemini(rows[i][TEXT_COL]);   // one UrlFetch per item
    sheet.getRange(i + 1, STATUS_COL + 1).setValue('done');
    sheet.getRange(i + 1, DRAFT_COL + 1).setValue(draft);
  }
}
 
function callGemini(text) {
  const res = UrlFetchApp.fetch(GEMINI_ENDPOINT, {
    method: 'post',
    contentType: 'application/json',
    headers: { 'x-goog-api-key': 'YOUR_API_KEY' },
    payload: JSON.stringify({ contents: [{ parts: [{ text: text }] }] }),
    muteHttpExceptions: true,
  });
  return JSON.parse(res.getContentText()).candidates[0].content.parts[0].text;
}

This code has a weakness that always surfaces on a busy day: there is no cap on the number of pending items. At a usual 3,000 items/day it takes just over 3,000 UrlFetch calls. But the day after a feature launch adds 40,000 reviews, it tries to process 43,000 at once and issues over 46,000 UrlFetch calls. Well past the 20,000 wall, it hits the urlfetch daily limit and throws mid-run.

Worse, the failure point moves around. Which item it dies on depends on how many UrlFetch calls other scripts made that day. Whatever stopped short carries over to the next day — but the naive version has no notion of "how far did I get" in budget terms, so the next day it fires all pending items at once again and hits the same wall. That was the loop I ran, a few days every month-end.

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
Understand, from reproducible code, how the UrlFetch daily call quota (20,000 calls/day on consumer accounts) is a third ceiling — distinct from the 6-minute runtime and trigger-count limits — that only bites on high-volume days
Copy a complete Apps Script token-bucket governor that keeps a daily budget ledger in Script Properties and resets it on the timezone boundary, not UTC
Verify with a deterministic simulation (backlog clears three days after a spike) that carrying work over to the next day converges instead of snowballing
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 Workspace × Gemini API Automation: Production Notes on 12 Apps Script Patterns
12 Gemini API + Apps Script patterns for Gmail, Docs, Sheets, and Calendar automation—plus the production snags I hit running this across four sites and an app support inbox: swallowed 429s, JSON code fences, the 6-minute cap, and flash-vs-pro routing, with measured numbers.
Workspace2026-07-01
When Two Triggers Write at Once, Your Gemini Result Quietly Vanishes — A Durable Result Store for Apps Script
Storing Gemini results from several Apps Script triggers loses writes through read-modify-write races and PropertiesService size limits. Build a result store that survives, using LockService, a durable sink, and idempotency keys.
Workspace2026-06-29
Keeping Apps Script + Gemini Automations on Least Privilege: Explicit Scopes and Catching Scope Creep
Apps Script automations that call Gemini quietly accumulate OAuth scopes. Here is how to declare explicit scopes in appsscript.json, catch scope creep in CI, and avoid forcing every user to re-consent.
📚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 →