Overzicht van Apps Script quota
Apps Script quota variëren per accounttype: persoonlijk (gratis Gmail) versus Google Workspace. Workspace-accounts hebben op de meeste services significant hogere limieten. De exacte getallen kunnen door Google worden bijgesteld, dus controleer bij twijfel altijd de officiële quotapagina.
Belangrijkste quota (geverifieerd, stand juni 2026):
| Service | Persoonlijk (Gmail) | Workspace |
|---|---|---|
| E-mailontvangers per dag | 100 | 1.500 |
| Triggers per gebruiker per script | 20 | 20 |
| Uitvoertijd per script-run | 6 min | 6 min |
| Totale trigger-runtime per dag | 90 min | 6 uur |
| UrlFetch-aanroepen per dag | 20.000 | 100.000 |
| Gelijktijdige uitvoeringen | 30 | 30 |
Twee verschillende uitvoertijd-limieten
Verwar de twee uitvoertijd-limieten niet. Elke afzonderlijke script-run mag maximaal 6 minuten duren. Daarnaast geldt een totale trigger-runtime per dag van 90 minuten (persoonlijk) of 6 uur (Workspace) voor al je automatische triggers samen.
Quota controleren
function controleerQuota() {
const resterende = MailApp.getRemainingDailyQuota();
Logger.log(`Resterende e-mailquota: ${resterende}`);
if (resterende < 50) {
Logger.log('Waarschuwing: weinig e-mailquota resterend');
}
}
MailApp.getRemainingDailyQuota() geeft het aantal resterende e-mailontvangers terug voor de huidige 24-uursperiode. Voor de meeste andere services bestaat geen vergelijkbare "remaining"-functie, dus die houd je zelf bij (zie de UrlFetch-teller verderop).
E-mailquota bewaken
function stuurEmailMetQuotaCheck(ontvanger, onderwerp, body) {
const resteren = MailApp.getRemainingDailyQuota();
if (resteren <= 0) {
Logger.log('E-mailquota bereikt, bericht in wachtrij geplaatst');
slaEmailOpInWachtrij(ontvanger, onderwerp, body);
return false;
}
if (resteren < 20) {
Logger.log(`Waarschuwing: slechts ${resteren} e-mails resterend`);
}
GmailApp.sendEmail(ontvanger, onderwerp, body);
return true;
}
function slaEmailOpInWachtrij(ontvanger, onderwerp, body) {
const cache = CacheService.getScriptCache();
const wachtrij = JSON.parse(cache.get('email_wachtrij') || '[]');
wachtrij.push({ontvanger, onderwerp, body, tijdstip: new Date().toISOString()});
cache.put('email_wachtrij', JSON.stringify(wachtrij), 86400);
}
CacheService is vluchtig
CacheService is geschikt voor kortstondige opslag, maar Google kan items vroegtijdig verwijderen bij geheugendruk. Voor een wachtrij die je echt niet wilt verliezen, gebruik je PropertiesService of een tabblad in een spreadsheet als duurzame opslag.
Uitvoertijdlimiet omzeilen
De 6-minuten uitvoerlimiet geldt per enkele script-run. Voor langlopende taken combineer je PropertiesService (voortgang opslaan) met time-based triggers (hervatten).
function verwerkInBatches() {
const MAX_UITVOERTIJD_MS = 5 * 60 * 1000;
const startTijd = Date.now();
const props = PropertiesService.getScriptProperties();
let startRij = parseInt(props.getProperty('VERWERK_VOORTGANG') || '1');
const blad = SpreadsheetApp.getActiveSheet();
const data = blad.getDataRange().getValues();
let verwerkt = 0;
while (startRij < data.length) {
if (Date.now() - startTijd > MAX_UITVOERTIJD_MS) {
props.setProperty('VERWERK_VOORTGANG', String(startRij));
Logger.log(`Uitvoertijd bijna bereikt, voortgang opgeslagen bij rij ${startRij}`);
return;
}
verwerkEnkeleRij(data[startRij]);
startRij++;
verwerkt++;
}
props.deleteProperty('VERWERK_VOORTGANG');
Logger.log(`Alle ${verwerkt} rijen verwerkt`);
}
function verwerkEnkeleRij(rij) {
Utilities.sleep(10);
}
We stoppen bewust op 5 minuten in plaats van 6, zodat er marge overblijft om de voortgang nog veilig op te slaan voordat Apps Script de run hard afkapt.
Trigger-limieten beheren
function haalAlleTriggersOp() {
const triggers = ScriptApp.getProjectTriggers();
Logger.log(`Aantal triggers: ${triggers.length}`);
triggers.forEach(t => {
Logger.log(`${t.getHandlerFunction()} - ${t.getEventType()} - ${t.getTriggerSource()}`);
});
return triggers;
}
function verwijderDubbeleTriggers() {
const triggers = ScriptApp.getProjectTriggers();
const gezien = new Set();
triggers.forEach(trigger => {
const key = `${trigger.getHandlerFunction()}_${trigger.getTriggerSource()}`;
if (gezien.has(key)) {
ScriptApp.deleteTrigger(trigger);
Logger.log(`Duplicaat trigger verwijderd: ${trigger.getHandlerFunction()}`);
} else {
gezien.add(key);
}
});
}
De limiet van 20 triggers geldt per gebruiker per script. Dubbele triggers ontstaan vaak doordat een installatie-functie meerdere keren wordt uitgevoerd zonder oude triggers op te ruimen. De functie hierboven dedupliceert ze.
UrlFetch-quota bewaken
const urlFetchTeller = {
aanroepen: 0,
limiet: 20000,
fetch(url, opties = {}) {
this.aanroepen++;
if (this.aanroepen > this.limiet * 0.9) {
Logger.log(`Nadering UrlFetch daglimiet (${this.aanroepen}/${this.limiet})`);
}
return UrlFetchApp.fetch(url, opties);
},
};
De daglimiet voor UrlFetch is 20.000 aanroepen op een persoonlijk account en 100.000 op een Workspace-account. Pas de limiet-waarde aan op je accounttype. Deze teller telt alleen aanroepen binnen één script-run, dus voor een sluitende telling over de hele dag schrijf je het totaal weg naar PropertiesService.
Quota-vriendelijke verwerking plannen
function planVerwerkingOver24Uur(aantalItems) {
const itemsPerUur = Math.ceil(aantalItems / 20);
Logger.log(`Planning: ${itemsPerUur} items per trigger-run over 20 uur`);
const bestaandeTriggers = ScriptApp.getProjectTriggers()
.filter(t => t.getHandlerFunction() === 'batchVerwerking');
bestaandeTriggers.forEach(t => ScriptApp.deleteTrigger(t));
ScriptApp.newTrigger('batchVerwerking')
.timeBased()
.everyHours(1)
.create();
PropertiesService.getScriptProperties().setProperties({
BATCH_GROOTTE: String(itemsPerUur),
BATCH_VOORTGANG: '0',
});
}
Houd rekening met de totale trigger-runtime
Een uurtrigger die elke run dicht tegen de 6 minuten aanloopt, verbruikt op een persoonlijk account snel je 90 minuten totale trigger-runtime per dag. Houd batches klein of upgrade naar Workspace (6 uur) als je veel volume verwerkt.
Wat gebeurt er als ik de uitvoertijdlimiet bereik?
Apps Script gooit de fout Exceeded maximum execution time en de script-run eindigt. Gebruik de aanpak met voortgang opslaan plus een time-based trigger om het werk te hervatten.
Kan ik de dagelijkse uitvoertijdlimiet vergroten?
Nee, de 6-uur totale trigger-runtime voor Workspace is een harde grens, net als de 90 minuten voor persoonlijke accounts. Optimaliseer je scripts of verdeel werk over meerdere kleinere runs.
Wanneer reset de quota?
Quota zijn per gebruiker en resetten 24 uur na de eerste aanroep van een service, niet op een vast moment zoals middernacht. De teller begint dus te lopen vanaf je eerste gebruik die dag.
Hoe vermijd ik de trigger-limiet van 20?
Gebruik één parametrische trigger die PropertiesService leest om te bepalen welk werk moet gebeuren, in plaats van een aparte trigger per taak.
Verschilt de UrlFetch-limiet tussen accounttypes?
Ja. Een persoonlijk account mag 20.000 UrlFetch-aanroepen per dag doen, een Workspace-account 100.000. Houd je verbruik bij als je veel externe API-calls maakt.
Tellen verzonden e-mails per bericht of per ontvanger?
De e-mailquota telt ontvangers, niet berichten. Eén e-mail naar tien ontvangers verbruikt tien van je daglimiet.
Langlopende verwerking met triggers opsplitten
- Sla de beginindex op in
PropertiesServicebij de eerste aanroep. - Meet de uitvoertijd in de verwerkingslus met
Date.now() - startTijd. - Als de tijdlimiet nadert (bijvoorbeeld 5 minuten): sla de huidige index op en
return. - Maak een
time-basedtrigger die de functie elk uur opnieuw aanroept. - Verwijder de trigger zodra de verwerking klaar is.
Quota zijn geen obstakels maar ontwerp-constraints. Door scripts te ontwerpen met quota-bewustzijn bouw je robuuste automatiseringen die ook bij grote volumes betrouwbaar blijven werken.