Google Apps Script Quotas and Limits: What AI Won't Tell You
Why This Matters
Google Apps Script is free. But “free” doesn’t mean “unlimited.” Google enforces daily quotas and execution limits on every Apps Script feature. Exceed them and your script stops; sometimes with an error message, sometimes silently.
These limits aren’t hidden; they’re documented on Google’s developer pages. But AI-generated scripts almost never account for them, and most tutorials skip them entirely. So businesses build automations that work perfectly on 20 test rows and collapse on 2,000 real ones.
Here’s what you need to know.
The Limits That Catch People
Execution Time Limit
The limit: 6 minutes per execution for most triggers. Up to 30 minutes for some Google Workspace account executions.
What this means: Your script has 6 minutes to do its job. If it’s processing data row by row with individual API calls, 6 minutes runs out fast.
What trips it: Large dataset processing, multiple API calls per row, complex calculations on big datasets, and anything that calls an external API with variable response times.
How to handle it:
- Batch operations (read/write arrays, not individual cells)
- Checkpoint-based processing (track progress, resume on next run)
- Time-aware loops (check elapsed time and exit gracefully before the limit)
Email Sending Quotas
The limits:
| Account Type | Daily Emails | Recipients per Email |
|---|---|---|
| Consumer (gmail.com) | 100 | 100 |
| Google Workspace | 1,500 | 500 |
What this means: A Google Workspace account can send 1,500 emails per day via Apps Script. Sounds generous until you realise that a notification system sending to 20 people, 5 times a day, uses 100 emails, and that’s one automation.
What trips it: Notification-heavy systems, mass email campaigns (don’t use Apps Script for these; use a dedicated email service), and systems with error notifications that fire too frequently.
How to handle it:
- Track daily email count in Script Properties
- Batch notifications into digest emails instead of individual sends
- Use Gmail drafts as a queue when approaching limits
- For genuine mass email, use a dedicated service and trigger it from Apps Script
Spreadsheet Operations
The limits:
- Read/write cells per day: varies, but the practical limit is usually hit through execution time, not raw call count
- Maximum cells in a spreadsheet: 10 million
- Maximum simultaneous connections: ~50 users
What trips it: Scripts that read individual cells in loops (each read is a network call), spreadsheets that have grown to millions of cells, and concurrent users triggering the same script simultaneously.
How to handle it:
- Always use
getValues()andsetValues()for batch operations - Archive old data to separate sheets/spreadsheets
- Use Lock Service to prevent concurrent execution conflicts
URL Fetch (External API Calls)
The limits:
| Feature | Consumer | Google Workspace |
|---|---|---|
| URL Fetch calls per day | 20,000 | 100,000 |
| URL Fetch payload size | 50MB | 50MB |
| Response size | 50MB | 50MB |
What this means: If your script calls external APIs, you have 20,000-100,000 calls per day. Each UrlFetchApp.fetch() counts as one call.
What trips it: Scripts that poll external services frequently, webhook-heavy integrations, and any automation that calls an API per row in a large dataset.
How to handle it:
- Cache API responses in Script Properties or Sheets to avoid repeat calls
- Use batch API endpoints where available
- Implement exponential backoff for rate-limited APIs
Trigger Limits
The limits:
- Maximum triggers per user per script: 20
- Maximum total triggers per script: 20
- Trigger execution frequency minimum: 1 minute (time-based)
What this means: You can’t create more than 20 triggers on a single script project. And time-based triggers can fire at most once per minute.
What trips it: Scripts that programmatically create triggers without cleanup (the duplicate trigger problem), and designs that assume sub-minute trigger frequency.
How to handle it:
- Always delete old triggers before creating new ones
- Design for trigger reuse, not trigger creation
- Use a single trigger that dispatches to multiple functions if needed
Drive Operations
The limits:
- File creation: varies by account type
- Shared Drive operations have additional restrictions
- Trash operations count toward quotas
What trips it: Document generators that create hundreds of files daily, file management scripts that move/copy large volumes, and scripts that don’t clean up temporary files.
How to handle it:
- Batch file operations where possible
- Implement file creation tracking
- Clean up temporary files in the same execution
Calendar Operations
The limits:
| Feature | Consumer | Google Workspace |
|---|---|---|
| Events created per day | 5,000 | 10,000 |
What trips it: Bulk calendar population (importing hundreds of events), and scripts that recreate events instead of updating existing ones.
The Limits AI Doesn’t Know About
Beyond the documented quotas, there are practical limits that come from experience:
Execution Overlap
If a time-based trigger fires every minute and an execution takes 2 minutes, you’ll have overlapping executions. Two scripts reading and writing the same spreadsheet simultaneously creates race conditions; corrupted data, duplicate rows, missing updates.
Solution: Use Lock Service to ensure only one execution runs at a time:
function processData() {
var lock = LockService.getScriptLock();
if (!lock.tryLock(10000)) {
// Another execution is running, skip this one
return;
}
try {
// ... do work
} finally {
lock.releaseLock();
}
}
Timezone Drift
Apps Script time triggers run in the script’s timezone (set in the project settings). If your data includes timestamps from users in different timezones, or if you’re comparing trigger execution time against sheet data, timezone mismatches create subtle bugs.
Dates that look correct in the spreadsheet can be off by hours in the script, causing records to be processed on the wrong day or missed entirely.
Quota Reset Timing
Quotas reset “24 hours after the first request”, not at midnight. If you hit your email quota at 2pm on Tuesday, it resets at 2pm on Wednesday. A script designed to “spread its work across the day” can still exhaust the quota if yesterday’s usage was front-loaded.
Permission Scope Creep
Apps Script authorisation is all-or-nothing per scope. Adding a Drive feature to an existing Gmail script may trigger a re-authorisation that breaks existing triggers. The script keeps running with the old scopes until a manual reauthorisation happens, and time-based triggers can’t prompt for reauthorisation.
Building With Limits in Mind
The goal isn’t to avoid limits; it’s to design for them. Production Apps Script should:
-
Know its quotas. Track daily usage of rate-limited features (emails sent, API calls made, files created).
-
Fail gracefully. When approaching a limit, pause and resume later; don’t crash and leave work half-done.
-
Log everything. When a quota is hit, the log should say what limit was reached, what work remains, and when the script will retry.
-
Alert on anomalies. If email usage suddenly spikes from 50/day to 500/day, something changed; flag it before it hits the limit.
-
Batch by default. Read arrays, not cells. Send digests, not individual notifications. Create files in batches, not one-by-one loops.
Need Help Building Within the Limits?
At Empower Automation, we build Google Apps Script solutions that respect Google’s quotas by design, not by accident. Every automation we deploy includes quota awareness, batch processing, and graceful degradation built in from the start.
Book a free 15-minute automation audit →
If you’ve got a script that’s hitting limits, or you want to build something that won’t, we’ll help you design it right the first time.
Nicola Berry is the founder of Empower Automation, based in Falkirk, Scotland. Building automation that works within the rules, and works reliably.
Professional Email & Tools for Your Business
Get you@yourcompany.com, plus video meetings, secure cloud storage, and the powerful admin controls you need to scale. Same tools I use to build your automations.