This is the full picture, pulled from Google's official Apps Script quotas documentation (last verified July 2026).
The Two Quota Tiers: Consumer vs. Workspace
Every Apps Script quota splits along one axis: personal Gmail account vs. Google Workspace account. Workspace gets materially better limits. But "better" still means "finite."
| Quota | Consumer (Gmail) | Google Workspace |
|---|---|---|
| Script runtime per execution | 6 minutes | 6 minutes |
| Daily script runtime | 1 hour | 6 hours |
| URL Fetch calls/day | 20,000 | 100,000 |
| URL Fetch data/day | 50 MB | 500 MB |
| Email recipients/day | 100 | 1,500 |
| Triggers per script | 20 | 20 |
| Script properties storage | 9 MB total, 500 KB/property | 9 MB total, 500 KB/property |
| CacheService item size | 100 KB | 100 KB |
The 6-minute per-execution cap is identical regardless of account type. That's the one that tends to hurt most in financial models. For a detailed breakdown of that specific limit and how to engineer around it, see Apps Script's 6-Minute Execution Limit: Official Quota.
Where the Official Quota Page Actually Lives
Google's authoritative source is the Apps Script quotas page under their developer documentation. The page lists limits across six categories: script runtime, spreadsheet operations, email, triggers, URL Fetch, and Properties/Cache services.
Google's documentation states directly: "The following limits apply to Google Apps Script projects." These caps apply at the account level, not the deployment type, meaning add-ons and standalone scripts share the same quotas.
The Quota That Kills FP&A Scripts: Execution Time
A script that loops through 3 years of monthly revenue by SKU, consolidates across 12 regional P&L tabs, and pushes results to a summary sheet can chew through 6 minutes faster than you'd expect.
The execution clock starts when the trigger fires, not when your code hits the expensive section. SpreadsheetApp.getActiveSpreadsheet(), Logger calls, and scope setup all count.
The fix: batch reads and writes. Never call getValue() or setValue() inside a loop.
// Slow: 500 individual calls - will exhaust execution time on large models
for (var i = 2; i <= 500; i++) {
var val = sheet.getRange(i, 3).getValue(); // One API call per row
sheet.getRange(i, 4).setValue(val * 1.08); // Another API call per row
}
// Fast: 2 calls total, regardless of row count
var data = sheet.getRange(2, 3, 499, 1).getValues(); // Single batch read
var output = data.map(function(row) { return [row[0] * 1.08]; });
sheet.getRange(2, 4, 499, 1).setValues(output); // Single batch write
For a model pulling =SUMIFS('P&L'!C:C, 'P&L'!B:B, ">=" & Assumptions!$B$3) across 48 periods, batching alone can drop a 7-minute script to under 90 seconds. The API call count matters more than the computational work.
Daily Runtime Caps: The Limit Nobody Plans For
The 1-hour/6-hour daily cap is usually invisible until it suddenly isn't. Here's the scenario: a time-based trigger running every 15 minutes to refresh a KPI dashboard, each run taking 3 minutes. That's 288 minutes of runtime per day, fine for Workspace and through the consumer 1-hour cap before 9 AM.
Google does not warn you when you're approaching the daily cap. The script just fails silently, and the error shows up in the Executions log hours later.
If you're running scheduled refreshes for a weekly board pack build or a daily revenue roll-up, you need to account for cumulative daily runtime, not just per-execution time.
Trigger Quotas: 20 Per Script
The hard limit is 20 time-driven triggers per script, and it's the same for both account tiers. Where it bites: complex automation that tries to chain multiple time-based triggers to work around the 6-minute cap. You can chain them, but with only 20 slots available per script across all users, that approach has a ceiling.
The cleaner pattern for long-running automation is continuations: at the end of each 5-minute chunk, the script saves its position to PropertiesService and fires a new trigger to pick up where it left off. This lets a single script process unlimited data across multiple runs without piling up trigger slots.
Email Quotas and Report Distribution
The gap between 100 and 1,500 email recipients per day matters once you're automating report distribution. A script emailing a monthly P&L summary to 150 stakeholders works fine on Workspace and fails on a personal account.
The quota counts recipients, not emails sent. One email to 150 addresses consumes 150 quota. 150 emails to 1 address each also consumes 150. There's no workaround at the Apps Script layer. For lists larger than 1,500, the standard pattern is routing through Google Groups: one email to a group counts as 1 recipient toward the daily limit.
Checking Your Quota Usage in the Official Dashboard
There's no real-time quota meter inside Apps Script. What you can actually see:
- Executions log: In the Apps Script editor, the Executions panel (left nav) logs every run with duration and exit status - completed, timed out, or quota exceeded.
- Google Workspace Admin Console: Workspace admins can view aggregate script activity across the org via Reports > Apps > Apps Script.
- A Sheets-based audit log in your script: The practical approach for anything touching a live model.
function runWithQuotaLogging() {
// Log every run to a dedicated ErrorLog tab in your model
var log = SpreadsheetApp.openById('YOUR_WORKBOOK_ID')
.getSheetByName('ErrorLog');
try {
runMainProcess(); // Your actual function here
log.appendRow([new Date(), 'SUCCESS', Session.getActiveUser().getEmail()]);
} catch(e) {
// Catches quota errors, timeout errors, permission errors
log.appendRow([new Date(), 'ERROR', e.message]);
}
}
Add this wrapper to any script that touches a live financial model. When a quota error silently kills your monthly close automation overnight, you want a log row.
Where ModelMonkey Fits
The quota problem with Apps Script is a throughput problem: more data to process than a 6-minute window allows, and engineering a proper continuation pattern takes a few hours most analysts don't have on a close deadline.
ModelMonkey handles AI-layer work inside Google Sheets directly - formula generation, data transformations, cross-tab analysis on a 14-tab model with $4.2M ARR and 38 SKUs - without hitting Apps Script execution limits, because it runs against its own backend rather than inside the Apps Script sandbox. For contribution margin by SKU 20 minutes before a board call, that distinction matters.
Try ModelMonkey free for 14 days - it works in both Google Sheets and Excel.