Website under construction feedback appreciated at [email protected]
← Terug naar blog
aws

Lambda cold starts: vijf manieren om ze te omzeilen

Yair Knijn · · 5 min lezen

Een Lambda-functie die na een paar minuten inactiviteit wordt aangeroepen, heeft een cold start. Dat betekent dat AWS een nieuwe execution environment moet opstarten, je code moet laden en de runtime moet initialiseren voordat je handler iets doet. Voor een API die mensen daadwerkelijk gebruiken, is dat zichtbaar.

Hier zijn vijf tactieken om het probleem aan te pakken, van het meest effectief naar het meest pragmatisch.

Wat een cold start precies kost

Cijfers variëren per runtime, regio en package-grootte, maar de ordes van grootte zijn consistent:

RuntimeGemiddelde cold start
Python 3.12200-400 ms
Node.js 22200-500 ms
Java 21 (zonder SnapStart)1.000-3.000 ms
.NET 8500-1.500 ms
Go 1.22100-200 ms

Bij een p99-target van 500 ms is een Java cold start van 2 seconden onacceptabel. Bij een asynchrone verwerking die toch al seconden duurt, merk je het nauwelijks.

De ernst van het probleem hangt ook af van hoe vaak cold starts voorkomen. Een functie met 1.000 requests per minuut heeft bijna nooit cold starts. Een functie die eens per uur wordt aangeroepen, heeft ze vrijwel altijd.

1. Provisioned Concurrency

Provisioned Concurrency houdt een opgegeven aantal execution environments permanent warm. Er is geen cold start voor die instances; ze zijn klaar om requests te verwerken zodra ze binnenkomen.

De kosten zijn tweeledig: je betaalt voor de provisioned instances zelf (ook als ze idle staan) en voor de requests die ze verwerken. Voor een gemiddelde functie van 512 MB die je op 5 provisioned instances zet, kost dat ruwweg $20-40 per maand, afhankelijk van de regio.

Gebruik dit voor functies die gebruikersgericht zijn en een latency-SLA hebben. Gebruik het niet voor batch-jobs of event-driven achtergrondverwerking.

Application Auto Scaling kan Provisioned Concurrency aan- en uitzetten op een schema, wat nuttig is als je een voorspelbaar verkeerspatroon hebt.

2. SnapStart voor Java

SnapStart is specifiek voor Java 11 en hoger. Het werkt door een snapshot te nemen van de execution environment na initialisatie en die snapshot te herstellen bij een cold start. In plaats van de JVM opnieuw op te starten, laad je een kant-en-klare geheugenimage.

De praktische winst is groot. Een Java-functie die normaal 2-3 seconden cold start heeft, komt met SnapStart op 200-500 ms. Dat is vergelijkbaar met Python of Node.js.

Activeer het in de function configuration. Er zijn randgevallen te kennen: als je code singletons of tijdstempel-gebaseerde logica initialiseert tijdens de init-fase, moet je de CRaC-interfaces implementeren om resources correct te sluiten en te heropenen na restore. De AWS-documentatie dekt dit. Voor de meeste Spring Boot of Micronaut-applicaties werkt het zonder aanpassingen.

3. Kleinere deployment packages

Hoe groter je package, hoe langer het duurt om het te laden. Dit is een simpele relatie.

Een Node.js-functie die de volledige aws-sdk v2 importeert, heeft een package van meerdere MB’s. Met de AWS SDK v3 importeer je alleen de clients die je nodig hebt:

import { S3Client, GetObjectCommand } from "@aws-sdk/client-s3";

Dat scheelt snel 10-15 MB. Op een cold start is dat waarneembaar.

Gebruik een bundler (esbuild, rollup) om tree-shaking toe te passen. Lever alleen de code die je runtime daadwerkelijk nodig heeft. Voor Python: gebruik Lambda Layers voor grote dependencies die je deelt over meerdere functies, zodat ze apart gecached worden.

4. Kies de juiste runtime

Als je geen sterke taalvoorkeur of bestaande codebase hebt, is de runtimekeuze een performance-keuze.

Python en Node.js hebben de laagste cold starts voor toepassingen die weinig zware initialisatie doen. Go is nog sneller maar heeft een kleinere community en minder AWS-SDKs beschikbaar. Java is trager tenzij je SnapStart gebruikt.

Dit is een beslissing die je het best vooraf neemt. Van Java migreren naar Python midden in een project kost meer dan een cold start.

5. Keep-warm pings

De meest bekende omweg: stuur elke 5-10 minuten een ping naar je functie via EventBridge Scheduler of CloudWatch Events om de execution environment warm te houden.

Dit is technisch gezien een anti-patroon. AWS geeft geen garanties over hoe lang een execution environment in leven blijft na een keep-warm ping. In de praktijk werkt het, maar er zijn uitzonderingen.

Voor functies met laag volume waarbij Provisioned Concurrency te duur is, is het alsnog de moeite waard. Zet een eenvoudige if (event.source === 'warmup') return check bovenaan je handler zodat je de logica niet uitvoert op ping-requests.

Wil je dieper gaan in serverless architectuur en Lambda-optimalisatie? Bekijk het overzicht van serverless en AWS-trainingen op ict-trainingen.com.

Wat je vandaag kunt doen

Kijk eerst naar je cold start frequentie in CloudWatch. Filter op de Init Duration-metric in je Lambda-logs. Als minder dan 1% van je requests een cold start heeft, is er geen actie nodig. Als het hoger is:

  • Python of Node.js, grote package: stap 3 eerst.
  • Java: zet SnapStart aan, meten daarna.
  • Gebruikersgericht met SLA: Provisioned Concurrency op minimale instances.
  • Laag volume, geen budget: keep-warm ping als tijdelijke maatregel.

Cold starts zijn oplosbaar. De juiste aanpak hangt af van je runtime, volume en budget, niet van een generiek advies.

lambda aws performance serverless