Naar inhoud
lightbulb Welkom op de nieuwe kennisbank | We hebben de docs volledig vernieuwd met meer dan 160 features. Bekijk wat nieuw isarrow_forward

Quota en limieten in Apps Script

Begrijp de dagelijkse en per-minuut quota van Apps Script en leer strategieen om binnen de grenzen te blijven, met de actuele limieten voor consumenten- en Workspace-accounts.

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
info

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);
}
warning

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',
  });
}
lightbulb

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

  1. Sla de beginindex op in PropertiesService bij de eerste aanroep.
  2. Meet de uitvoertijd in de verwerkingslus met Date.now() - startTijd.
  3. Als de tijdlimiet nadert (bijvoorbeeld 5 minuten): sla de huidige index op en return.
  4. Maak een time-based trigger die de functie elk uur opnieuw aanroept.
  5. 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.