Die Serverless-Lüge
Die Serverless-Lüge
Es gibt ein Szenario, das jeden Solopreneur und Architekten nachts wachhält: Der "Black Friday" Sale. Dein Marketing war exzellent, der Traffic explodiert, und deine Serverless Functions skalieren wunderschön auf 10.000 Instanzen hoch.
Doch dann passiert es. Du hast nur noch ein Ticket auf Lager.
Zwei User, nennen wir sie Alice und Bob, klicken in der exakt gleichen Millisekunde auf "Kaufen".
Deine API prüft die Datenbank: SELECT stock FROM products WHERE id = 1.
Die Datenbank antwortet beiden Funktionen: stock: 1.
Beide Funktionen führen den Kauf aus und dekrementieren den Stock.
Das Ergebnis: stock: -1. Du hast ein Ticket verkauft, das nicht existiert.
Das Problem ist nicht die Datenbank
Der Industrie-Reflex ist jetzt oft: "Wir brauchen Transaktionen! Wir brauchen Kubernetes! Wir brauchen Stateful Server!" Das ist falsch. Das ist Enterprise Bloat.
Das Problem ist, dass Serverless per Definition stateless ist. Jede Funktionsinstanz weiß nichts von der anderen. Wenn wir versuchen, dieses Problem auf Datenbank-Ebene mit komplexen Row-Level-Locks zu lösen, machen wir unsere Datenbank zum Flaschenhals (Single Point of Failure).
Die Lösung liegt nicht in der Persistenz-Schicht, sondern in der Middleware. Wir brauchen einen Türsteher, der schneller ist als Postgres. Wir brauchen Atomic Locking.
Die Architektur der Atomaren Sperre
Die Architektur der Atomaren Sperre
Um Race-Conditions in einer verteilten Umgebung zu besiegen, nutzen wir einen Mechanismus, der außerhalb unserer Datenbank lebt: Redis. Speziell Vercel KV oder Upstash (Serverless Redis).
Der Trick ist nicht das Speichern von Daten, sondern das atomare Setzen eines "Flags".
Der SETNX-Befehl
Redis bietet einen Befehl namens SETNX (Set if Not Exists). Das ist unser magischer Schalter.
Wenn zwei Prozesse gleichzeitig versuchen, den gleichen Key zu setzen, gewinnt nur einer. Der zweite bekommt ein 0 (False) zurück. Keine Exceptions, keine Wartezeiten, einfach ein boolesches "Nein".
Wöchentliche Insights zu AI-Architektur. Kein Spam.
Der Flow sieht so aus:
- Request kommt rein.
- Middleware: Versuch, einen Lock-Key zu setzen (z.B.
lock:product:123). - Erfolg (Lock erhalten): Führe die DB-Transaktion durch.
- Fehler (Lock verweigert): Wirf sofort einen Fehler (
429 Too Many Requestsoder409 Conflict). Blockiere den Datenbank-Zugriff komplett. - Cleanup: Lösche den Lock-Key (oder lass ihn per TTL auslaufen).
Warum TTL (Time-To-Live) kritisch ist
Ein häufiger Fehler: Was passiert, wenn deine Function abstürzt, nachdem sie den Lock geholt hat, aber bevor sie ihn löscht?
Ohne TTL bleibt das Produkt für immer gesperrt. Das ist ein "Deadlock".
Deshalb nutzen wir immer SET key value NX EX 10. Der Lock löscht sich nach 10 Sekunden automatisch, selbst wenn der Server brennt.
Das ist "Lean Architecture". Wir schützen die langsame Ressource (Postgres) durch eine extrem schnelle, atomare Schicht (Redis). Wir schreiben keinen komplexen Queue-Code. Wir nutzen existierende Infrastruktur als Hebel.
Das Urteil
Das Urteil: Lean Architecture gewinnt
Viele Entwickler greifen bei Concurrency-Problemen sofort zu Message Queues (RabbitMQ, Kafka) oder versuchen, komplexe Saga-Pattern zu implementieren. Das ist oft Over-Engineering.
Für 99% der Anwendungsfälle – Ticketverkäufe, limitierte Drops, Username-Reservierungen – reicht ein einfaches SETNX.
Warum dieser Ansatz gewinnt:
- Geschwindigkeit: Redis antwortet in <1ms. Deine UX leidet nicht.
- Kosten: Du zahlst keine Idle-Time für Queue-Server. Vercel KV ist Serverless.
- Simplicity: Du hast gerade 500 Zeilen Queue-Management-Code durch 20 Zeilen Locking-Logik ersetzt.
Code ist eine Verbindlichkeit (Liability). Je weniger Code du schreibst, um Datenintegrität zu garantieren, desto besser ist deine Architektur. Redis ist hier der Hebel, der es dir erlaubt, mit Serverless zu skalieren, ohne die Kontrolle über deinen State zu verlieren.
Du brauchst kein Kubernetes. Du brauchst nur einen besseren Türsteher.