Die AWS-Lambda-Funktion, die du seit Jahren baust, heißt seit letzter Woche „Event Function". Code und Konfiguration ändern sich dadurch nicht, API und CloudFormation sprechen weiter von Function, aber der Name verrät, was AWS vorhat: Lambda ist kein einzelnes Produkt mehr, sondern eine Familie aus drei Compute-Modellen mit sehr unterschiedlichen Regeln.
Wir haben vor Kurzem eine vollständig serverlose Plattform gebaut, die über 650 Messen mit zwei KI-Agents aktuell hält. Lambda-Stufen, SQS (Simple Queue Service) dazwischen, Job-Tracking in DynamoDB, eigene Retry- und Backoff-Logik, ein Fallback-Agent als Container-Lambda. Jede Ankündigung der letzten 15 Monate haben wir durch genau diese Brille gelesen: Was würden wir heute anders bauen? Und was ist schöne Technik, die uns nichts bringt?
Die Kurzfassung
| Event Functions | Web Functions | MicroVMs | |
|---|---|---|---|
| Aufruf | Events: SQS, S3, EventBridge, API Gateway … | HTTPS-Endpoint | Eigener HTTPS-Endpoint pro VM |
| Programmiermodell | Handler bekommt JSON-Event | Dein Code lauscht auf einem Port | Beliebiger Prozess aus Dockerfile |
| Requests pro Umgebung | Einer (außer Managed Instances) | Bis zu 128 gleichzeitig (Default 64) | Eine VM pro Nutzer/Session |
| Maximale Laufzeit | 15 Minuten pro Aufruf, mit Durable Functions bis zu einem Jahr gesamt | 15 Minuten pro Request | 8 Stunden, mit Suspend/Resume |
| Abrechnung | Wall-Clock × konfiguriertes Memory | Aktive CPU-Zeit + tatsächlich belegtes Memory | vCPU- und GB-Sekunden, im Suspend keine Compute-Kosten |
| Gut für | Backend-Verarbeitung, Pipelines | Nutzerseitige APIs, Server-Side Rendering (SSR) | Fremden oder KI-generierten Code ausführen |
Dazu kommen zwei Querachsen, die nur Event Functions betreffen: Managed Instances bestimmen, wo deine Funktion läuft. Durable Functions bestimmen, wie lange sie läuft und wie sie sich ihren State merkt.
Event Functions: Das alte Lambda bekommt neue Optionen
Durable Functions: Die Änderung, auf die wir gewartet haben
In unserer Messe-Pipeline steckt erstaunlich viel Code, der mit der eigentlichen Aufgabe nichts zu tun hat. Job-Tracking in DynamoDB, damit wir wissen, in welcher Stufe eine Messe gerade hängt. Backoff und Retries. Die Übergabe an den Fallback-Agent, wenn der Primär-Agent sein Budget aufgebraucht hat. Jede Stufe ist eine eigene Lambda, verbunden über SQS, weil eine einzelne Funktion nach 15 Minuten abgeschossen wird.
Durable Functions (seit Dezember 2025) setzen genau hier an. Du schreibst den Workflow als normalen Code und kapselst Arbeitsschritte in step-Aufrufe. Lambda speichert das Ergebnis jedes Schritts. Fällt die Funktion aus oder wartet sie, wird sie später neu aufgerufen und überspringt alles, was schon erledigt ist. Während einer Wartezeit fallen keine Compute-Kosten an.
import { withDurableExecution, DurableContext } from "@aws/durable-execution-sdk-js";
import { runPrimaryAgent, runFallbackAgent, saveResult } from "./agents";
export const handler = withDurableExecution(
async (event: { fairId: string }, context: DurableContext) => {
let result = await context.step("primary-agent", async () =>
runPrimaryAgent(event.fairId),
);
// Verzweigt nur auf dem gespeicherten Ergebnis eines Steps, daher replay-sicher
if (!result.complete) {
result = await context.step("fallback-agent", async () =>
runFallbackAgent(event.fairId, result),
);
}
await context.step("save", async () => saveResult(event.fairId, result));
return { fairId: event.fairId, status: result.status };
},
);
Die Queues zwischen den Agent-Stufen, ihre Dead-Letter-Queues (DLQs) und die Statustabelle schrumpfen auf eine Funktion. Das ist der Teil, der uns überzeugt.
Der Haken ist derselbe wie bei Temporal oder Azure Durable Functions: Replay. Beim Wiederaufruf läuft dein Code von vorne, nur die Steps werden aus dem gespeicherten State bedient. AWS formuliert es unmissverständlich: Code außerhalb eines Steps muss eine pure function des Inputs und der bisherigen Step-Ergebnisse sein. Ein Date.now(), Math.random() oder eine frisch generierte UUID im Kontrollfluss liefert beim Replay einen anderen Wert, und dann nimmt der Code einen anderen Pfad als beim ersten Lauf. Solche Bugs sind schwer zu finden, weil sie nur auftreten, wenn tatsächlich ein Replay passiert.
Die zweite Falle hat uns beim Lesen der Doku überrascht, weil sie genau unseren Fall trifft. Durable Functions funktionieren mit allen Event Source Mappings, also auch mit SQS. Ein Event Source Mapping (ESM) ruft die Funktion aber synchron auf, und dann ist die gesamte Execution auf 15 Minuten begrenzt, über alle Replays hinweg. Wer länger braucht, schaltet eine kleine Starter-Lambda dazwischen, die die Durable Function asynchron aufruft. Für eine Agent-Pipeline, deren Fallback-Agent so lange iteriert, bis die Daten vollständig sind, ist das kein Detail.
Was du sonst wissen solltest:
- Nur bei neuen Funktionen. Die
DurableConfigwird beim Anlegen gesetzt, bestehende Funktionen lassen sich nicht umstellen. Aufgerufen wird immer mit qualifizierter ARN (Amazon Resource Name, mit Version oder Alias). Eine laufende Execution bleibt auf ihrer Version. - Pflichtfeld
ExecutionTimeoutfür die Gesamtdauer, maximal 366 Tage. Der normale Timeout von höchstens 15 Minuten gilt weiter pro Aufruf. - DLQs ja, Lambda Destinations nein. Wer seine Fehlerbehandlung auf Destinations aufgebaut hat, muss umbauen. Fehlgeschlagene asynchrone Executions wiederholt Lambda nicht automatisch.
- Idempotenz nur am Start. Ein
DurableExecutionNamebeim Invoke verhindert, dass dasselbe Event zwei Executions startet (bei der Messe-Pipeline wäre das die Messe-ID). Steps selbst laufen standardmäßig at least once, der Code darin muss also idempotent sein. Über ein ESM gibt es diese Namens-Idempotenz nicht, ein Grund mehr für die Starter-Lambda. - Kosten: 8 $ pro Million Durable Operations (Start, jeder Step, jedes Wait zählt), dazu 0,25 $ pro GB geschriebenem State und 0,15 $ pro GB-Monat Retention. Die Compute-Kosten der Replays kommen obendrauf. Für eine Pipeline mit wenigen, langen Steps ist das vernachlässigbar. Bei tausenden kleinen Steps pro Execution solltest du nachrechnen.
- SDKs gibt es für TypeScript/JavaScript, Python, Java (GA seit April 2026), Go und .NET.
Durable Functions oder Step Functions? Wenn der Workflow im Kern Code ist und einem Team gehört: Durable Functions. Wenn du viele AWS-Services ohne eigenen Code orchestrierst, der Betrieb den State jeder Execution visuell sehen will oder fachliche Leute den Workflow mitlesen sollen: Step Functions. Für unsere Agent-Pipeline wäre es Durable Functions. Die Logik „Primär-Agent, bei Misserfolg Fallback mit Iterationslimit" ist in TypeScript lesbarer als in ASL (Amazon States Language).
Managed Instances: Lambda auf deinen EC2-Instanzen
Managed Instances (seit Ende November 2025) lassen Event Functions auf EC2-Instanzen in deinem Account laufen. AWS kümmert sich um OS-Patches, Load Balancing und Skalierung, du wählst Instanztypen und ein Verhältnis von Memory zu vCPU (2:1, 4:1 oder 8:1). Programmiermodell und Trigger bleiben gleich. Seit März 2026 gehen bis 32 GB Memory und 16 vCPUs, seit Mai Scheduled Scaling.
Das Preismodell erklärt, für wen sich das lohnt: EC2-Preis plus 15 % Management-Gebühr auf den On-Demand-Preis plus 0,20 $ pro Million Requests. Savings Plans und Reserved Instances greifen auf den EC2-Anteil. Interessant wird es also bei gleichmäßig hoher Last, für die du ohnehin Compute-Rabatte hast, oder bei Workloads, die ein CPU-zu-Memory-Verhältnis brauchen, das klassisches Lambda nicht hergibt. GPUs gibt es nicht.
Was du dafür aufgibst:
- Scale-to-Zero. Ohne Traffic bleibt die Funktion auf dem konfigurierten Minimum, standardmäßig drei Instanzen für Redundanz über Availability Zones (AZs). Auf null geht es nur per Zeitplan.
- Ein Request pro Umgebung. Eine Umgebung verarbeitet mehrere Aufrufe gleichzeitig, je nach Runtime über Threads, Worker oder (bei Python) mehrere Prozesse, die sich
/tmpteilen. Code, der sich darauf verlässt, dass globale Variablen nur einem Request gehören, bricht. Die Doku warnt ausdrücklich: Der Code muss thread-safe sein. - Schnelles Hochskalieren. Skaliert wird asynchron nach CPU-Last. Verdoppelt sich der Traffic innerhalb von fünf Minuten, kann es zu Throttling kommen.
Für die Messe-Plattform: nein. Unsere Last kommt in Schüben, wenn Messen neu erfasst oder Saisons gewechselt werden. Dazwischen passiert wenig. Das ist der Fall, für den klassisches Lambda gemacht ist.
Tenant Isolation Mode
Für SaaS-Anbieter: Seit November 2025 kann Lambda Execution Environments nach Tenant trennen. Der Caller übergibt eine Tenant-ID, und eine Umgebung, die Tenant A bedient hat, sieht nie einen Request von Tenant B. Wer bisher pro Tenant eine eigene Funktion deployt hat, um genau das zu erreichen, kann sich das sparen.
Die Einschränkungen sind deutlich: nur beim Anlegen der Funktion aktivierbar, nicht kombinierbar mit Function URLs, Provisioned Concurrency, SnapStart oder Managed Instances. Und Event Source Mappings können die Tenant-ID nicht mitgeben. AWS empfiehlt dafür eine Router-Lambda, die die ID aus der SQS-Nachricht oder dem EventBridge-Event liest und die isolierte Funktion damit aufruft. Wer Tenants nur auf Datenebene trennt (bei uns über das DynamoDB-Schema), braucht das Feature nicht zwingend.
Kleinere Änderungen, die Workarounds überflüssig machen
Keine davon ist einen eigenen Blogpost wert. Zusammen räumen sie aber einiges auf, was wir in Projekten über Jahre mitgeschleppt haben:
- 1 MB statt 256 KB Payload bei SQS (August 2025), asynchronen Lambda-Aufrufen (Oktober 2025) und EventBridge (Januar 2026). Das Claim-Check-Pattern (Payload nach S3, nur den Key verschicken) brauchst du für Nachrichten bis 1 MB nicht mehr. Jede angefangenen 64 KB über 256 KB werden allerdings als zusätzlicher Request abgerechnet.
- Response Streaming bis 200 MB statt 20 MB, seit April 2026 in allen kommerziellen Regionen. Weiterhin nur mit Node.js und Custom Runtimes.
- Provisioned Mode für SQS Event Source Mappings (November 2025): feste Poller-Kapazität mit Minimum und Maximum, abgerechnet pro Event Poller Unit. Interessant, wenn du nach einem Lastsprung nicht minutenlang auf die Skalierung warten willst. Seit August sind bis zu 10.000 Poller pro ESM möglich.
- Self-managed Code Storage (Juli 2026): Mit
S3ObjectStorageMode=REFERENCEliest Lambda den Code direkt aus deinem eigenen S3-Bucket, ohne Kopie und ohne Storage-Limit. Das Default-Limit für den Lambda-verwalteten Code Storage ist parallel von 75 GB auf 300 GB pro Region gestiegen. Wer schon einmal ein Deployment wegenCodeStorageExceededExceptiondebuggen musste, weiß das zu schätzen. - Metadata Endpoint (März 2026): Die Funktion kann ihre AZ-ID abfragen (etwa
euc1-az2) und Requests an Datenbank-Replikas oder Caches in derselben AZ schicken. Spart Latenz und Cross-AZ-Traffic. - S3 Files (April 2026): S3-Buckets lassen sich per NFS als Dateisystem in Lambda mounten. Die Funktion muss dafür im VPC laufen, mit Managed Instances geht es nicht.
- Neue Runtimes: Python 3.14 und Node.js 24 (November 2025, Node 24 ohne Callback-Handler), Rust GA (November 2025), .NET 10 (Januar 2026), Ruby 4.0 (April 2026). Node.js 26 und Python 3.15 sind seit August in Public Preview, GA ist für November angekündigt.
- Remote Debugging aus VS Code (Juli 2025) gegen eine echte Lambda in AWS, über das AWS Toolkit und IoT Secure Tunneling. Klingt nach Spielerei, spart aber genau die Stunden, in denen ein Bug nur mit echten IAM-Rechten und echtem VPC auftritt.
Eine Sache, die im letzten Jahr oft falsch weitererzählt wurde: „Lambda braucht kein NAT Gateway mehr." Dahinter steckt kein neues Feature, sondern ein AWS-Blogpost zu IPv6 vom November 2025. Lambda im Dual-Stack-VPC kann schon seit 2023 über ein kostenloses Egress-only Internet Gateway ins Internet. Das hilft aber nur bei Zielen, die IPv6 sprechen. Für IPv4-only-APIs und feste ausgehende IPs brauchst du das NAT Gateway weiterhin.
Web Functions: Das Lambda, das wir 2020 wollten
Web Functions sind seit dem 12. Oktober verfügbar und die größte konzeptionelle Änderung. Dein Code ist ein normaler HTTP-Server, Express oder Hono laufen ohne Adapter. Kein Handler, kein JSON-Event, kein serverless-http. Eine Umgebung bedient bis zu 128 Requests gleichzeitig.
Wir haben Web Functions noch nicht selbst betrieben. Was hier steht, kommt aus der AWS-Doku und aus Ben Steeles sehr gründlichen Notizen, der die Laufzeitumgebung auseinandergenommen hat. Er nennt es „das Lambda, das ich 2020 wollte". Dem schließen wir uns an, aus einem Grund, der in den Ankündigungen etwas untergeht: dem Abrechnungsmodell.
Warum das Abrechnungsmodell der eigentliche Punkt ist
Klassisches Lambda rechnet Wall-Clock-Zeit mal konfiguriertem Memory ab. Wartet deine Funktion acht Sekunden auf eine LLM-Antwort, zahlst du acht Sekunden. Das war bei Datenbank-Calls mit 20 ms egal. Bei Anwendungen, die ständig auf Modell-APIs warten, ist es der größte Kostenblock.
Web Functions rechnen aktive CPU-Zeit und das tatsächlich belegte Memory über die Lebensdauer der Umgebung ab. Eine Beispielrechnung mit den us-east-1-Preisen für einen Endpoint, der pro Request 8 Sekunden auf ein LLM wartet und dabei 50 ms CPU verbraucht, bei einer Million Requests im Monat:
| Event Function (arm64, 512 MB) | Web Function | |
|---|---|---|
| Requests | 0,20 $ | 0,30 $ |
| Compute | 1 Mio. × 8 s × 0,5 GB × 0,0000133334 $ ≈ 53,30 $ | 1 Mio. × 0,05 vCPU-s × 0,0000276944 $ ≈ 1,40 $ |
| Memory | im Compute enthalten | eine Umgebung, 200 MB belegt, ganzer Monat × 0,0000036667 $/GB-s ≈ 1,90 $ |
| Summe | ≈ 53,50 $ | ≈ 3,60 $ |
Die Annahmen sind bewusst einfach: gleichmäßige Last (im Schnitt drei parallele Requests, das schafft eine Umgebung locker), kein Datentransfer. Bei echten Lastspitzen laufen mehr Umgebungen und der Memory-Anteil steigt, denn auch Idle-Zeit wird berechnet. Die Größenordnung bleibt trotzdem: Für I/O-lastige Endpoints ist das Faktor 10 und mehr. Umgekehrt gilt: Bei CPU-lastigen Requests mit kurzer Laufzeit sind Web Functions nicht automatisch billiger, der Request-Preis liegt 50 % über dem klassischen.
In der Messe-Plattform hilft uns das trotzdem nur zum Teil. Die Agents hängen an SQS, und Web Functions werden über ihren HTTPS-Endpoint aufgerufen. Kein SQS-Consumer, kein S3-Trigger. AWS empfiehlt für alles Eventgetriebene ausdrücklich Event Functions. Das ist eine saubere Trennung: Web Functions für alles, was ein Mensch oder ein anderer Service per HTTP aufruft, Event Functions für alles dahinter.
Was dich beim Umstieg erwischt
Die Einschränkungen zum Launch sind deutlich, und einige davon sind nicht offensichtlich:
- Nur Node.js 24 auf arm64, feste 2 vCPU und 2 GB pro Umgebung, fünf Regionen (us-east-1, us-east-2, us-west-2, Tokio, Irland). Frankfurt fehlt. Python-, Java- oder .NET-Teams bleiben vorerst bei Event Functions.
- Code nur aus versioniertem S3.
aws lambda-web deploylädt einen lokalen Ordner selbst hoch, aber unter der Haube ist ein Zip in einem S3-Bucket mit Versionierung der einzige Weg. Pipelines, die aufupdate-function-code --zip-fileaufbauen, müssen umgebaut werden. Wird die Objektversion gelöscht, ist die Revision dauerhaft kaputt. - Keine Lambda Extensions. Die AWS-Doku schweigt dazu, Steele hat aber nachgesehen: Die Extensions- und Telemetry-APIs antworten mit 404. Lambda Extensions für Datadog, Secrets-Caching oder OpenTelemetry fallen damit weg, Telemetrie muss aus deinem Prozess heraus verschickt werden.
- Geteilter State. Viele Requests teilen sich einen Node-Prozess. Ein Modul-globaler Cache, ein gesetzter Request-Kontext oder ein Singleton mit Nutzerdaten war bei klassischem Lambda harmlos. Jetzt leakt er zwischen Requests verschiedener Nutzer. Das ist der Fehler, den wir beim Migrieren bestehender Funktionen am ehesten erwarten.
- Eine Sekunde nach SIGTERM. Danach ist der Prozess weg. Graceful Shutdown mit langen Flushes klappt nicht. Der Server muss außerdem innerhalb von 10 Sekunden nach dem Start auf seinem Port lauschen.
- Idle kostet. Memory wird über die ganze Lebensdauer der Umgebung berechnet. Eine feste Idle-Zeit nennt AWS nicht, Steele hat beobachtet, dass eine ungenutzte Umgebung nach rund fünf Minuten abgebaut wurde.
- Logs mehrfach. Es gibt eine Log-Gruppe pro Region plus eine zentrale in der Home-Region, beide standardmäßig mit Retention Never expire. Bei einem Multi-Region-Endpoint über drei Regionen speicherst du jede Logzeile viermal. Retention also gleich mitsetzen.
- Nur HTTP/1.1, keine WebSockets. Der
Upgrade-Header wird entfernt, und Lambda reicht den kompletten Request-Body weiter, bevor deine Antwort beginnt. Response Streaming und damit Server-Sent Events funktionieren.
Steele hat außerdem beobachtet, dass ein gesetztes maxEnvironments bei Lastspitzen zu 429-Fehlern führt (Platform.EndpointMaxEnvThrottle), während die Plattform ohne diese Grenze großzügig vorprovisioniert. 429er werden nicht gepuffert. Wer aus Kostengründen eine Obergrenze setzt, sollte das vorher unter Last testen.
Eingebaut sind dafür Multi-Region mit latenzbasiertem Routing über eine globale URL, immutable Revisions mit gewichteten Canaries und VPC-Anbindung über Network Connectors. Für ein Produkt in der ersten Version ist das viel.
MicroVMs: Kein Lambda im gewohnten Sinn
Lambda MicroVMs (seit Juni 2026) teilen sich mit klassischem Lambda vor allem die Firecracker-Basis und den Namen. Du bekommst eine isolierte, stateful VM aus einem Dockerfile, mit eigenem HTTPS-Endpoint (HTTP/2, gRPC, WebSockets) und bis zu 8 Stunden Laufzeit. Bei Suspend und Resume bleiben Memory- und Disk-State erhalten, der nächste Request weckt die VM wieder auf. Standardmäßig startet sie mit 1 vCPU und 2 GB und burstet bei Bedarf bis 4 vCPU und 8 GB.
Was fehlt, ist horizontales Skalieren. Das Modell ist eine VM pro Nutzer oder Session, und jede startest du selbst mit run-microvm. Laut AWS gehen einige hundert pro Minute, aber die Orchestrierung baust du: Wer bekommt welche VM, wann wird suspendiert, wann beendet. Jede eingehende Verbindung braucht außerdem ein Auth-Token, das du über die API erzeugst.
Der Anwendungsfall ist eng und klar: Code ausführen, den du nicht selbst geschrieben hast. Code-Interpreter für Agents, Sandboxen für Nutzer-Plugins, Notebooks, Coding-Agents, die ein Repository auschecken und Tests laufen lassen. Für Zugriff ins eigene VPC gibt es Network Connectors in der neuen Lambda Core API: Elastic Network Interfaces (ENIs) einmal anlegen (das dauert etwa zehn Minuten) und beim Start an MicroVMs hängen. Ins Internet kommt die VM auch ohne.
Die naheliegende Alternative ist Bedrock AgentCore Runtime. Einen offiziellen Vergleich gibt es nicht. Yan Cui beschreibt es so: AgentCore Runtime verhält sich zu MicroVMs wie Fargate zu EC2. AgentCore nimmt dir Routing, Skalierung, Auth und Versionierung ab, MicroVMs geben dir Kontrolle über Image, Netzwerk und Lifecycle, plus Suspend/Resume. Wenn du einen Agent betreiben willst, ist AgentCore der kürzere Weg. Wenn du eine Sandbox-Plattform baust, MicroVMs.
Für die Messe-Plattform brauchen wir MicroVMs nicht. Unser Fallback-Agent ist eigener Code, kein fremder Input. Dass er als Container-Lambda läuft, liegt an der Größe seiner Dependencies, nicht an Sicherheitsanforderungen.
Was nehmen wir wofür?
| Workload | Unsere Wahl | Alternative, wenn … |
|---|---|---|
| Asynchrone Pipeline, eventgetrieben | Event Function | — |
| Mehrstufiger Workflow mit Retries, Warten, Fallbacks | Event Function + Durable Functions (bei SQS mit Starter-Lambda) | Step Functions, wenn viele Service-Integrationen ohne eigenen Code oder visuelles Monitoring gefragt sind |
| Nutzerseitige API, SSR, I/O-lastig | Web Function | Event Function + Function URL, wenn nicht Node.js oder Region fehlt; Fargate, wenn WebSockets |
| Gleichmäßige Dauerlast, Savings Plans vorhanden | Event Function auf Managed Instances | Fargate/ECS, wenn ihr ohnehin Container betreibt |
| Fremder oder KI-generierter Code | MicroVMs | Bedrock AgentCore, wenn es ein Agent ist und keine Sandbox-Plattform |
| GPU, Laufzeiten über 8 Stunden | Nicht Lambda | ECS/EC2, SageMaker |
Was wir heute anders bauen würden
Ehrlich betrachtet: weniger, als die Menge der Ankündigungen vermuten lässt.
Die SQS-Kette zwischen den Agent-Stufen würden wir durch eine Durable Function ersetzen, gestartet von einer schmalen Lambda, die die Messe-ID als Execution Name mitgibt. Das spart Infrastruktur, vor allem aber Code, der nur existiert, weil Lambda bisher nichts über mehrere Aufrufe hinweg behalten konnte. Die nutzerseitige API wäre ein Kandidat für Web Functions, sobald es sie in Frankfurt gibt und wir für die Observability nicht mehr auf Extensions angewiesen sind. Alles andere bleibt, wie es ist. Die Pipeline ist schubweise, eventgetrieben und stateless, und dafür war klassisches Lambda immer gut.
Die neuen Primitive lösen jeweils ein konkretes Problem, das viele Teams bisher mit Workarounds umschifft haben. Wer keines dieser Probleme hat, muss nichts tun. Wer eins hat, sollte jetzt nachsehen, ob der Workaround noch nötig ist.