- 2026.07.29 What Breaks When Apps Script Projects Sprawl
- 2026.07.16 Why a Daily Apps Script Trigger Suddenly Stops
- 2026.07.15 What Breaks When Customer Data Lives in Browser Storage
- 2026.07.07 When the Browser Throws Your Data Away: The Green Checkmark Lies
- 2026.07.07 Installed ≠ Working: the Backup Trigger Never Ran Once
- 2026.07.07 GAS Has No Gradual Rollout: One 'Correct' Check Locks Out Every User
- 2026.07.07 Sheets Turns Your Text Into a Date: When '2026-06' Blocks Completion Forever
- 2026.06.18 An App Where Many Write to One Sheet: Concurrency, Duplicates, and Export Design
- 2026.06.12 Don't Read Cells One at a Time: Service Calls Are the Real Cost
- 2026.06.11 Stuffing JSON or Images into a Sheet Cell Will Break It
- 2026.06.10 One Deploy Setting Decides Your Security Model: Execute as / Access
- 2026.06.09 The 6-Minute GAS Limit: Chunk and Resume Before It Kills You You are here
- 2026.06.08 PropertiesService Is Not a Database: the 9KB Wall
- 2026.06.07 Why Saving a Screen as an Image Freezes on Mobile
- 2026.06.06 Concurrent Writes to the Same Sheet Break: LockService and the 30-Run Ceiling
- 2026.06.05 Your /exec URL Must Not Change on Every Redeploy
- 2026.06.04 External Calls Fail Sometimes: Exponential Backoff and a Retry Budget
- 2026.06.03 HtmlService Apps: Shell First, Then Async Load and Mobile Back
- 2026.06.02 When to Graduate from GAS: Limit Signals and Moving to an External DB
- 2026.06.01 Adding a Brain and an Engine Room to GAS: Vertex AI and Cloud Run
The 6-Minute GAS Limit: Chunk and Resume Before It Kills You
Apps Script kills any single run at 6 minutes. Design bulk jobs as chunk + cursor + time-trigger resume, or you get the half-processed-data accident.
A single execution is force-killed at 6 minutes. Try to process 10,000 rows in one loop, hit the limit, and the script dies mid-run: leaving you half-processed. Run it again and it re-touches rows it already handled.
Why it matters
Half-applied data is worse than untouched data. You don’t know how far it got, so you need manual recovery: and that time eats the time automation was supposed to save. Trigger runtime also has its own daily cap (roughly 90 min/day on a consumer account).
The fix: chunk + cursor + trigger resume
Don’t try to finish in one shot. Save your position (a cursor) and use a time trigger to resume the next chunk.
const JOB_KEY = "sync.cursor";
function runSyncJob() {
const lock = LockService.getScriptLock();
if (!lock.tryLock(10000)) return; // prevent overlap
try {
const props = PropertiesService.getScriptProperties();
const cursor = Number(props.getProperty(JOB_KEY) || 0);
const result = processChunk(cursor, 300); // 300 rows at a time
if (result.done) {
props.deleteProperty(JOB_KEY);
deleteTriggers_("runSyncJob"); // clean up when finished
return;
}
props.setProperty(JOB_KEY, String(result.nextCursor));
scheduleOnce_("runSyncJob", 60 * 1000); // resume in 1 min
} finally {
lock.releaseLock();
}
}
function scheduleOnce_(handler, delayMs) {
deleteTriggers_(handler);
ScriptApp.newTrigger(handler).timeBased().after(delayMs).create();
}
function deleteTriggers_(handler) {
ScriptApp.getProjectTriggers()
.filter((tr) => tr.getHandlerFunction() === handler)
.forEach((tr) => ScriptApp.deleteTrigger(tr));
}
Easy to miss
- Always delete triggers. You get 20 triggers per script. If you don’t delete the existing same-handler trigger before creating a one-shot, you hit the cap fast.
- Prevent overlap. Use
LockServiceso a trigger that overlaps the previous run doesn’t process the same cursor twice. - Clean up on finish. Delete the cursor and trigger when done, or an empty job keeps firing every minute.
Deeper: size chunks by measuring
Start chunk size at 100–500 rows and tune against real run time. If one chunk passes half of the 6 minutes, shrink it. One line to keep: split into units that finish under 6 minutes, save your place, and resume.
Frequently asked questions
- Why does my Google Apps Script stop at 6 minutes?
- Apps Script force-kills any single execution at about 6 minutes (consumer accounts). Process a bulk job in one loop and you hit the limit mid-run, leaving the data half-applied.
- How do I get around the 6-minute execution limit?
- Don't finish in one run. Save your position as a cursor, then resume the next chunk with a time-based trigger (chunk + cursor + trigger resume). Use LockService to prevent overlapping runs.
- Do triggers remove the time limit?
- No. Total trigger runtime is also capped (about 90 minutes/day on consumer accounts). Size your chunks and run frequency to stay within that budget.
- 2026.07.29 What Breaks When Apps Script Projects Sprawl
- 2026.07.16 Why a Daily Apps Script Trigger Suddenly Stops
- 2026.07.15 What Breaks When Customer Data Lives in Browser Storage
- 2026.07.07 When the Browser Throws Your Data Away: The Green Checkmark Lies
- 2026.07.07 Installed ≠ Working: the Backup Trigger Never Ran Once
- 2026.07.07 GAS Has No Gradual Rollout: One 'Correct' Check Locks Out Every User
- 2026.07.07 Sheets Turns Your Text Into a Date: When '2026-06' Blocks Completion Forever
- 2026.06.18 An App Where Many Write to One Sheet: Concurrency, Duplicates, and Export Design
- 2026.06.12 Don't Read Cells One at a Time: Service Calls Are the Real Cost
- 2026.06.11 Stuffing JSON or Images into a Sheet Cell Will Break It
- 2026.06.10 One Deploy Setting Decides Your Security Model: Execute as / Access
- 2026.06.09 The 6-Minute GAS Limit: Chunk and Resume Before It Kills You You are here
- 2026.06.08 PropertiesService Is Not a Database: the 9KB Wall
- 2026.06.07 Why Saving a Screen as an Image Freezes on Mobile
- 2026.06.06 Concurrent Writes to the Same Sheet Break: LockService and the 30-Run Ceiling
- 2026.06.05 Your /exec URL Must Not Change on Every Redeploy
- 2026.06.04 External Calls Fail Sometimes: Exponential Backoff and a Retry Budget
- 2026.06.03 HtmlService Apps: Shell First, Then Async Load and Mobile Back
- 2026.06.02 When to Graduate from GAS: Limit Signals and Moving to an External DB
- 2026.06.01 Adding a Brain and an Engine Room to GAS: Vertex AI and Cloud Run