Serverless: Wie die Cloud das Programmieren verändert

Ein Einstieg für Entwicklerteams: Funktionen statt Server, Ereignisse statt Dauerbetrieb – mit Beispielcode, Kaltstarts und Kosten im Überblick
Aktualisiert:
Abstract
- #Serverless Computing
- #Cloud-Entwicklung
- #Backend-Entwicklung
- #Cloud-Infrastruktur
- #Functions as a Service
- #AWS Lambda
- #Google Cloud Functions
- #Azure Functions
- #Firebase
Was sich am Code ändert, wenn kein eigener Server mehr läuft, und worauf Einsteiger achten sollten
Ein Handwerksbetrieb möchte auf seiner Website ein Anfrageformular. Früher hätte das bedeutet: einen Server mieten, Betriebssystem und Webserver einrichten, Updates einspielen, Backups planen. Für ein Formular, das vielleicht zwanzig Mal am Tag abgeschickt wird, ist das viel Aufwand. Mit Serverless schreibt ein Entwickler eine einzelne Funktion, lädt sie beim Cloudanbieter hoch und bekommt eine Adresse, an die das Formular seine Daten schickt. Um alles darunter kümmert sich der Anbieter.
Dieses Modell hat nicht nur den Betrieb verändert, sondern auch die Art, wie Backend-Code geschrieben wird. Funktionen statt Anwendungen, Ereignisse statt Dauerschleifen, Konfiguration statt Serverpflege. Dieser Überblick richtet sich an Entwicklerinnen, Entwickler und technisch Interessierte, die verstehen möchten, wie Serverless im Alltag funktioniert und wo die Grenzen liegen.
Serverless kurz erklärt: Code ohne eigenen Server
Natürlich laufen auch Serverless-Anwendungen auf Servern. Der Unterschied: Ihr Team bekommt diese Server nie zu sehen. Es gibt keine Maschine, auf die man sich per SSH einloggt, und keine Kapazität, die man vorab bucht. Der Anbieter startet den Code, wenn er gebraucht wird, verteilt ihn bei Last auf viele Instanzen und fährt ihn wieder herunter, wenn nichts zu tun ist.
Eine Alltagsanalogie hilft beim Verständnis. Ein eigener Server ist wie ein Firmenwagen: Er kostet Geld, auch wenn er auf dem Hof steht, und jemand muss sich um Reifen und Inspektion kümmern. Serverless ähnelt eher dem Taxi. Sie zahlen pro Fahrt, und um das Fahrzeug kümmert sich ein anderer. Bei gelegentlichen Fahrten ist das günstig und bequem, wer täglich viele Stunden unterwegs ist, fährt mit dem eigenen Wagen oft billiger.
Technisch steckt hinter dem Begriff vor allem Functions as a Service (FaaS): Sie stellen einzelne Funktionen bereit, die bei einem Ereignis ausgeführt werden. Dazu kommen verwaltete Dienste wie Datenbanken, Dateispeicher oder Warteschlangen, die ebenfalls nach Nutzung abgerechnet werden. Welche strategischen Fragen das für Unternehmen aufwirft, von Anbieterbindung bis Datenschutz, behandelt unser Beitrag zu Chancen und Herausforderungen der Serverless-Architektur. Hier geht es um die Sicht der Entwicklung.
Wie sich das Programmieren verändert
Wer bisher klassische Webanwendungen gebaut hat, etwa mit Express, Spring oder Django, muss bei Serverless an einigen Stellen umdenken.
Ereignisse statt Dauerbetrieb. Eine klassische Anwendung startet einmal und wartet dann auf Anfragen. Eine Serverless-Funktion existiert nur für die Dauer eines Aufrufs. Ausgelöst wird sie durch ein Ereignis: eine HTTP-Anfrage, eine neue Datei im Speicher, einen Eintrag in der Datenbank, eine Nachricht in einer Warteschlange oder einen Zeitplan wie „jede Nacht um zwei Uhr“.
Zustandslosigkeit. Eine Funktion darf sich nicht darauf verlassen, dass Daten im Arbeitsspeicher den nächsten Aufruf überleben. Der nächste Aufruf landet womöglich auf einer ganz anderen Instanz. Sitzungsdaten, Zwischenergebnisse und Zähler gehören in eine Datenbank oder einen Cache. Wer diese Regel verletzt, erhält Fehler, die nur unter Last auftreten.
Kleine, klar abgegrenzte Einheiten. Statt einer großen Anwendung mit vielen Routen entstehen viele kleine Funktionen mit je einer Aufgabe. Das erleichtert Tests und Änderungen, macht aber die Zusammenhänge weniger sichtbar. Wie man solche ereignisgetriebenen Abläufe sinnvoll zuschneidet, beschreibt der Beitrag zur Event-driven Architecture mit Serverless.
Infrastruktur wird Teil des Codes. Welche Funktion auf welches Ereignis reagiert, wie viel Speicher sie bekommt und welche Rechte sie hat, steht in Konfigurationsdateien im selben Repository. Das Prinzip heißt Infrastructure as Code und sorgt dafür, dass sich eine Umgebung jederzeit reproduzieren lässt.
Rechte sind Feinarbeit. Jede Funktion braucht ihre eigene, möglichst enge Berechtigung. Eine Funktion, die nur Bestellungen liest, sollte keine Kundendaten löschen dürfen. Diese Feinarbeit ist aufwendiger als bei einem einzelnen Server, verkleinert aber den Schaden, wenn eine Funktion fehlerhaft ist oder angegriffen wird.
Die großen Plattformen im Überblick
Alle großen Cloudanbieter haben einen FaaS-Dienst im Programm. Die Grundidee ist überall gleich, die Details unterscheiden sich.
| Plattform | Anbieter | Besonderheit |
|---|---|---|
| AWS Lambda | Amazon Web Services | Ältester und am weitesten verbreiteter Dienst, sehr viele Auslöser aus dem AWS-Ökosystem |
| Azure Functions | Microsoft | Enge Anbindung an Microsoft 365 und .NET, Ablaufsteuerung über Durable Functions |
| Cloud Run functions | Google Cloud | Früher Google Cloud Functions, läuft heute auf der Containerplattform Cloud Run |
| Cloud Functions for Firebase | Google (Firebase) | Auf Web- und App-Projekte zugeschnitten, mit lokalem Emulator und Firestore-Anbindung |
| Cloudflare Workers | Cloudflare | Führt Code in Rechenzentren nahe beim Nutzer aus, sehr kurze Startzeiten |
Unterstützt werden fast überall JavaScript, TypeScript und Python, bei den großen Cloudanbietern meist auch Java, C# und Go. Welche Plattform passt, hängt weniger vom Funktionsdienst ab als vom Rest der Umgebung: Wer bereits Daten und Benutzerkonten bei einem Anbieter hat, bleibt meist dort.
Ein Beispiel mit Firebase: HTTP-Endpunkt und reaktive Funktion
Firebase eignet sich gut, um das Prinzip auszuprobieren, weil Datenbank, Funktionen und ein lokaler Emulator aus einer Hand kommen. Einen Überblick über die Plattform selbst gibt unser Beitrag zur App-Entwicklung mit Firebase. Das folgende Beispiel greift das Anfrageformular aus der Einleitung auf. Es nutzt die zweite Generation der Cloud Functions for Firebase und TypeScript.
Zunächst eine Funktion, die auf HTTP-Anfragen reagiert und eine neue Anfrage in der Datenbank Firestore speichert:
// functions/src/restful/anfragen.ts
import { onRequest } from 'firebase-functions/v2/https';
import { initializeApp } from 'firebase-admin/app';
import { getFirestore, FieldValue } from 'firebase-admin/firestore';
initializeApp();
const db = getFirestore();
export const anfrageAnlegen = onRequest(
{ region: 'europe-west3' }, // Rechenzentrum in Frankfurt
async (req, res) => {
if (req.method !== 'POST') {
res.status(405).send('Nur POST ist erlaubt');
return;
}
const { name, email, nachricht } = req.body ?? {};
if (!email || !nachricht) {
res
.status(400)
.json({ fehler: 'E-Mail und Nachricht sind Pflichtfelder' });
return;
}
const eintrag = await db.collection('anfragen').add({
name: name ?? '',
email,
nachricht,
eingegangen: FieldValue.serverTimestamp(),
});
res.status(201).json({ id: eintrag.id });
},
);
Die zweite Funktion wird nicht direkt aufgerufen. Sie reagiert, sobald in Firestore ein neues Dokument in der Sammlung anfragen entsteht:
// functions/src/reactive/anfragen.ts
import { onDocumentCreated } from 'firebase-functions/v2/firestore';
import { logger } from 'firebase-functions';
export const anfrageMelden = onDocumentCreated(
{ document: 'anfragen/{anfrageId}', region: 'europe-west3' },
async (event) => {
const daten = event.data?.data();
if (!daten) return;
logger.info('Neue Anfrage eingegangen', {
id: event.params.anfrageId,
email: daten.email,
});
// Hier würde z. B. eine Benachrichtigung an den Vertrieb verschickt
},
);
Die Aufteilung zeigt ein typisches Muster: Der HTTP-Endpunkt nimmt die Daten an, prüft sie und antwortet schnell. Alles, was danach passiert, erledigt eine reaktive Funktion im Hintergrund. Fällt der E-Mail-Versand einmal aus, bekommt die Person am Formular trotzdem sofort eine Bestätigung.
Entwickelt und getestet wird lokal mit der Firebase-Kommandozeile. Der Emulator bildet Funktionen und Datenbank auf dem eigenen Rechner nach, sodass nicht jeder Testlauf in der Cloud landet:
npm install -g firebase-tools
firebase init # Functions, Firestore und Emulators auswählen
firebase emulators:start # lokale Testumgebung starten
firebase deploy --only functions # Funktionen in die Cloud übertragen
Für den Einsatz in der Cloud setzt Firebase einen Tarif mit nutzungsabhängiger Abrechnung voraus. Ein produktives Formular bräuchte außerdem Schutz vor automatisierten Spam-Einsendungen, etwa über Firebase App Check oder ein Captcha.
Wenn aus einer Funktion fünfzig werden
Einzelne Funktionen sind schnell geschrieben. Schwierig wird es, wenn ein Projekt wächst und aus drei Funktionen fünfzig werden. Ohne Ordnung entsteht dann ein Geflecht, in dem niemand mehr weiß, welche Funktion was auslöst.
Bewährt hat sich eine Trennung nach Art des Auslösers und nach fachlichem Bereich:
- RESTful-Funktionen reagieren auf HTTP-Anfragen und bilden die öffentliche Schnittstelle, etwa für eine App oder ein Webfrontend.
- Reaktive Funktionen werden durch Datenänderungen, Dateien, Nachrichten oder Zeitpläne ausgelöst und laufen im Hintergrund.
- Fachliche Gruppen wie Bestellungen, Zahlungen oder Benutzer bündeln zusammengehörige Funktionen in eigenen Ordnern.
Eine zentrale Datei sammelt die Exporte, damit die Plattform alle Funktionen findet:
// functions/src/index.ts
export { anfrageAnlegen } from './restful/anfragen';
export { anfrageMelden } from './reactive/anfragen';
Gemeinsamer Code, etwa für Validierung oder Datenbankzugriffe, gehört in eigene Module, die alle Funktionen nutzen. Wichtig ist außerdem, dass reaktive Funktionen damit rechnen, mehrfach ausgelöst zu werden. Die meisten Plattformen garantieren nur, dass ein Ereignis mindestens einmal zugestellt wird. Eine Funktion sollte deshalb so geschrieben sein, dass ein doppelter Aufruf keinen doppelten Schaden anrichtet, also etwa keine zweite Rechnung verschickt. Weitere Regeln für Logging, Fehlerbehandlung und Sicherheit fasst unser Beitrag mit Best Practices für Serverless-Architekturen zusammen.
Kaltstarts und Kosten: was Einsteiger wissen sollten
Zwei Fragen kommen bei Serverless fast immer, und beide lassen sich knapp beantworten.
Kaltstarts: Wurde eine Funktion eine Weile nicht genutzt, muss der Anbieter beim nächsten Aufruf erst eine neue Instanz starten und den Code laden. Dieser Kaltstart verzögert die Antwort, je nach Sprache und Paketgröße um Sekundenbruchteile bis zu wenigen Sekunden. Schlanke Funktionen in JavaScript, Python oder Go starten schneller als große Java-Anwendungen. Für Hintergrundaufgaben spielt das kaum eine Rolle, bei einer API, auf die Nutzer warten, schon eher. Abhilfe schaffen kleine Pakete und Mindestinstanzen, die der Anbieter dauerhaft warm hält. Diese kosten allerdings auch dann Geld, wenn niemand sie nutzt.
Kosten: Abgerechnet werden in der Regel die Zahl der Aufrufe und die Rechenzeit, multipliziert mit dem zugewiesenen Arbeitsspeicher. Bei AWS Lambda erfolgt die Abrechnung auf die Millisekunde genau. Kleine Projekte bleiben oft im kostenlosen Kontingent der Anbieter. Teuer wird es bei gleichmäßig hoher Dauerlast, bei langen Laufzeiten und bei Nebenkosten, die in der Funktionsrechnung gar nicht auftauchen: Datenübertragung, API-Gateway, Protokollspeicher. Eine ausführliche Kostenbetrachtung mit Rechenbeispielen finden Sie im Beitrag zu Vorteilen, Herausforderungen und Kosteneffizienz von Serverless.
Ein praktischer Rat: Richten Sie vom ersten Tag an Budgetwarnungen ein. Angenommen, eine Funktion schreibt in dieselbe Datenbank, deren Änderungen sie auslösen: Dann ruft sie sich in einer Endlosschleife selbst auf, und die Plattform stellt dafür klaglos immer neue Instanzen bereit.
Was das für Entwicklerteams bedeutet
Serverless hat das Programmieren in der Cloud tatsächlich verändert, aber anders, als es das Marketing der frühen Jahre versprach. Server verschwinden nicht, und auch nicht jede Anwendung wird zur Sammlung kleiner Funktionen. Geblieben ist ein Werkzeug mit klarem Profil: Es ist stark bei ereignisgesteuerten Aufgaben, unregelmäßiger Last, Integrationen und Hintergrundjobs. Für langlaufende Prozesse, dauerhaft hohe Last oder Anwendungen, die zwischen Anbietern wechseln müssen, sind Container oft die bessere Wahl.
Für Entwicklerteams verschiebt sich die Arbeit. Weniger Zeit fließt in Serverpflege, mehr in Architektur, Berechtigungen, Überwachung und das Denken in Ereignissen. Wer bisher vor allem klassische Webanwendungen gebaut hat, braucht dafür etwas Einarbeitung, vor allem beim Testen und bei der Fehlersuche über mehrere Funktionen hinweg.
Unsere Empfehlung: Beginnen Sie mit einer überschaubaren Aufgabe am Rand Ihres Systems, etwa einem Formular, einem Webhook oder einem nächtlichen Bericht. Daran lernt das Team die Plattform kennen, ohne das Kerngeschäft zu riskieren. Wenn Sie dabei Unterstützung suchen, von der Plattformwahl bis zur Schulung des Teams, finden Sie auf unserer Seite zu Serverless Computing Beratung, Coaching und Seminare.
Häufige Fragen zu Serverless
Ist Serverless dasselbe wie Cloud Computing?
Nein. Serverless ist eine bestimmte Form von Cloud Computing, bei der Sie keine Server oder virtuellen Maschinen verwalten und nach tatsächlicher Nutzung zahlen. Wer in der Cloud eine virtuelle Maschine mietet, nutzt zwar die Cloud, betreibt aber weiterhin einen eigenen Server.
Welche Programmiersprache eignet sich für Serverless?
Am verbreitetsten sind JavaScript beziehungsweise TypeScript und Python, weil sie schnell starten und von allen Plattformen unterstützt werden. Java und C# funktionieren ebenfalls, haben aber tendenziell längere Kaltstarts. Entscheidend ist meist, welche Sprache das Team bereits gut beherrscht.
Kann man Serverless-Funktionen lokal testen?
Ja, zumindest teilweise. Firebase bietet einen eigenen Emulator, für AWS gibt es AWS SAM, für Azure die Azure Functions Core Tools. Die Logik einer Funktion lässt sich zudem mit normalen Unit-Tests prüfen, wenn sie sauber vom Auslöser getrennt ist. Das Zusammenspiel mehrerer Cloud-Dienste lässt sich lokal aber nie vollständig nachbilden.
Ist Serverless sicher?
Der Anbieter übernimmt Updates für Betriebssystem und Laufzeitumgebung, was eine häufige Fehlerquelle beseitigt. Für den eigenen Code, die eingebundenen Bibliotheken, die Berechtigungen der Funktionen und den Schutz personenbezogener Daten bleibt Ihr Team verantwortlich. Ein typisches Einfallstor sind Funktionen, die mehr dürfen, als ihre Aufgabe erfordert.
Kategorien