Skip to content
Serverless auf AWS: Was es bedeutet, wie man es codet und wann es sich lohnt
← ← Zurück zu Gedanken Cloud

Serverless auf AWS: Was es bedeutet, wie man es codet und wann es sich lohnt

Du hast den Begriff „serverless" hunderte Male gehört. Und jedes Mal fühlt sich jemand berufen zu präzisieren: „Es heißt nicht, dass es keine Server gibt." Richtig. Die Server existieren, aber sie sind nicht mehr dein Problem. AWS betreibt sie, skaliert sie, patcht sie — und du zahlst nur, wenn dein Code tatsächlich läuft. Kein Traffic? Keine Kosten.

In früheren Artikeln ging es um die Migration einer klassischen App (React + Node.js + PostgreSQL + Redis) auf EC2 mit Auto Scaling und Zero-Downtime Deployment. Jetzt die radikale Alternative: Was, wenn du Server komplett aus der Gleichung entfernst?

Was ist Serverless konkret?

Serverless bedeutet: Du schreibst Funktionen (Code-Stücke), die als Reaktion auf Ereignisse laufen — ein HTTP-Request, eine in S3 hochgeladene Datei, eine Nachricht in einer SQS-Queue, eine Änderung in der Datenbank. Du provisionierst keine Server, konfigurierst keine Auto Scaling Groups, denkst nicht daran, wie viel RAM eine Instanz hat.

Bei AWS baut sich das Serverless-Ökosystem aus ein paar zentralen Diensten auf:

AWS Lambda — die Compute-Engine. Du schreibst eine Funktion (Node.js, Python, Java, Go usw.), lädst sie hoch, und Lambda führt sie bei jedem eingehenden Event aus. Skalierung automatisch von null auf tausende parallele Ausführungen.

API Gateway — die Eintrittstür. Empfängt HTTP/HTTPS-Requests und leitet sie an Lambda-Funktionen weiter. Übernimmt Authentifizierung, Rate Limiting und API-Versionierung.

DynamoDB — die serverlose Datenbank. NoSQL, vollständig verwaltet, mit automatischer Skalierung und Latenz im Millisekundenbereich. Du zahlst pro Request und pro gespeichertem GB.

S3 + CloudFront — für das statische Frontend (React/Vue), wie in der klassischen Architektur.

SQS / SNS / EventBridge — für asynchrone Kommunikation zwischen Funktionen.

Wie sieht der Code einer Lambda-Funktion aus?

Von einem konkreten Beispiel: Ein Endpoint liefert eine Produktliste aus DynamoDB:

// handler.js
const { DynamoDBClient } = require('@aws-sdk/client-dynamodb');
const { DynamoDBDocumentClient, ScanCommand } = require('@aws-sdk/lib-dynamodb');

const client = new DynamoDBClient({});
const docClient = DynamoDBDocumentClient.from(client);

exports.getProducts = async (event) => {
  try {
    const result = await docClient.send(
      new ScanCommand({ TableName: 'Products' })
    );
    
    return {
      statusCode: 200,
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(result.Items)
    };
  } catch (error) {
    return {
      statusCode: 500,
      body: JSON.stringify({ error: 'Internal Server Error' })
    };
  }
};

Die Funktion bekommt ein event (mit Details zum HTTP-Request — Path, Headers, Body, Query-Parameter) und gibt ein Objekt mit statusCode, headers und body zurück. Das war’s. Kein Express-Setup, kein Server auf einem Port, keine Prozessverwaltung.

Der grundlegende Unterschied zur klassischen Node.js-App: Es gibt keinen dauerhaft laufenden Prozess. Die Funktion „wacht" bei jedem Request auf, führt den Code aus und stoppt. AWS hält einen Pool von Containern bereit, um Latenz zu minimieren (aber beim ersten Aufruf nach Inaktivität erlebst du einen „Cold Start" von 100–500 ms).

Wie deployt man?

Serverless-Deployment ist radikal anders als auf EC2. Du aktualisierst keine Instanzen, es gibt kein Rolling oder Blue/Green. Du lädst den Code hoch, und die neue Version ist live.

Option 1: AWS SAM (Serverless Application Model) — das verbreitetste Framework. Du definierst die Infrastruktur in einer template.yaml:

# template.yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31

Globals:
  Function:
    Runtime: nodejs20.x
    Timeout: 10
    MemorySize: 256

Resources:
  GetProductsFunction:
    Type: AWS::Serverless::Function
    Properties:
      Handler: handler.getProducts
      Events:
        Api:
          Type: HttpApi
          Properties:
            Path: /products
            Method: get
      Policies:
        - DynamoDBReadPolicy:
            TableName: Products

  ProductsTable:
    Type: AWS::DynamoDB::Table
    Properties:
      TableName: Products
      BillingMode: PAY_PER_REQUEST
      AttributeDefinitions:
        - AttributeName: id
          AttributeType: S
      KeySchema:
        - AttributeName: id
          KeyType: HASH

Deploy sind zwei Befehle:

sam build
sam deploy --guided

SAM packt den Code, erstellt einen CloudFormation-Stack, provisioniert Lambda, API Gateway und DynamoDB — alles aus einer Konfigurationsdatei. Update? Code oder Template anpassen und erneut sam deploy ausführen.

Option 2: Serverless Framework — beliebte Alternative mit großer Plugin-Welt. Nutzt serverless.yml statt template.yaml, Prinzip dasselbe.

Option 3: AWS CDK (Cloud Development Kit) — für alle, die Infrastruktur lieber in Code (TypeScript, Python) als in YAML definieren. Ausführlicher, aber flexibler und besser testbar.

CI/CD-Integration ist simpel. In GitHub Actions einen Step, der sam build && sam deploy --no-confirm-changeset ausführt. In GitLab CI/CD dasselbe. CodeDeploy brauchst du nicht mehr — SAM regelt alles über CloudFormation.

Die echten Vorteile von Serverless

Keine Infrastruktur-Verwaltung. Keine Server zum Patchen, kein OS zum Aktualisieren, keine Nginx-Config. Das Team konzentriert sich zu 100 % auf Code.

Skalierung auf null. Bei EC2 zahlst du selbst mit Auto Scaling mindestens 2 Instanzen 24/7 (~67 $/Monat). Bei Lambda, wenn niemand die API aufruft, sind die Kosten buchstäblich 0 $.

Bezahlung pro Ausführung. Lambda kostet 0,20 $ pro Million Requests plus 0,0000166667 $ pro GB-Sekunde Compute. Der Free Tier umfasst 1 Million Requests und 400.000 GB-Sekunden pro Monat — dauerhaft, nicht nur 12 Monate.

Konkretes Kostenbeispiel: Eine App mit 5 Millionen Requests pro Monat, je Funktion 256 MB Speicher und 200 ms durchschnittliche Laufzeit, kostet auf Lambda etwa 4–5 $/Monat. Dieselbe App auf EC2 mit ALB mindestens 90–100 $/Monat.

Sofort-Deploy. Code hochladen, Lambda liefert sofort. Kein Rolling Update, kein Downtime. Bei Bedarf Lambda-Aliase und Versionen für Canary-Deployment.

Eingebaute Resilienz. Lambda läuft automatisch in mehreren Availability Zones. Fällt eine Zone aus, geht der Traffic in andere. Nichts zu konfigurieren.

Die Nachteile, die du kennen solltest

Cold Starts. Wenn eine Funktion längere Zeit nicht aufgerufen wurde, kann der erste Aufruf 100–500 ms (oder mehr bei Java) länger dauern. Lösung: Provisioned Concurrency (vorgewärmte Funktionen), kostet aber extra.

15-Minuten-Limit. Eine Lambda-Funktion darf maximal 15 Minuten laufen. Lange Prozesse müssen in kleinere Schritte (Step Functions) zerlegt oder nach ECS/EC2 verlagert werden.

API Gateway Timeout: 29 Sekunden. Reagiert die Lambda-Funktion innerhalb von 29 Sekunden nicht über API Gateway, bekommt der Request einen Timeout. Für lange Operationen: asynchrones Muster — Funktion startet Verarbeitung, gibt Job-ID zurück, Client macht Polling.

Vendor Lock-in. Lambda-Code ist eng an das AWS-Ökosystem gebunden. Wechsel zu einem anderen Cloud-Anbieter bedeutet erhebliche Refaktorierung. Teilweise abmildern mit Frameworks wie Serverless Framework, die den Provider abstrahieren.

Schwierigeres Debugging. Du kannst nicht per SSH auf einen Server und nachschauen. Du bist auf CloudWatch Logs, X-Ray für Tracing und lokales Testen mit SAM CLI (sam local invoke) angewiesen.

Architektur-Komplexität. Eine App mit 50 Lambda-Funktionen, 10 SQS-Queues und 5 DynamoDB-Tabellen kann schwerer zu verstehen und zu debuggen sein als ein einzelner Node.js-Server.

Serverless vs. EC2: Wann was?

Serverless wählen, wenn: Traffic variabel oder unvorhersehbar ist (von 0 bis zu massiven Spitzen), du schnell live gehen willst, das Team klein ist und keine Infrastruktur verwalten will, die App sich natürlich in unabhängige Funktionen zerlegen lässt oder das Budget bei wenig Traffic minimiert werden soll.

EC2/Container wählen, wenn: du konstanten, vorhersehbaren Traffic hast (24/7 mit hoher Auslastung), die App Long-Running-Prozesse hat (WebSockets, Videoverarbeitung), du volle Kontrolle über die Laufzeitumgebung brauchst oder die bestehende App ein Monolith ist, der sich nicht leicht aufteilen lässt.

Die Hybrid-Variante ist oft die pragmatischste: Frontend auf CloudFront + S3, Haupt-API auf Lambda + API Gateway, schwere Hintergrund-Jobs auf ECS Fargate oder EC2. PostgreSQL bleibt auf RDS, Redis auf ElastiCache — nicht alles muss serverless sein.

Von der Theorie zur Praxis

Wenn du Serverless ausprobieren willst, ohne eine komplette Migration zu starten, beginne mit einem einzigen Endpoint. Erstelle eine Lambda-Funktion mit SAM, verbinde sie mit API Gateway und beobachte das Verhalten. Der AWS Free Tier deckt Experimente problemlos ab.

Der natürlichste erste Schritt: asynchrone Verarbeitung nach Lambda verlagern. E-Mails versenden, PDFs erzeugen, Bildverarbeitung, Cron-Jobs — alles ideale Kandidaten. Das Haupt-Backend kann auf EC2 bleiben, Lambda übernimmt Aufgaben, die nicht synchron antworten müssen.

Serverless ist kein „alles oder nichts". Es ist ein weiteres Werkzeug in deinem Werkzeugkasten — extrem stark im richtigen Kontext.


Veröffentlicht auf teninvent.ro — TEN INVENT S.R.L. bietet Beratung und Implementierung serverloser Lösungen auf AWS. Kontaktiere uns, um zu prüfen, ob Serverless zu deiner Anwendung passt.