Zum Hauptinhalt springen
Alle Artikel

Payload CMS auf Cloudflare D1: Was sich gegenüber Postgres ändert

Von Dominik Stein2 Min. LesezeitAktualisiert am

Payload läuft inzwischen offiziell auf Cloudflare Workers mit D1 als Datenbank. Für unser Template Payload Plus haben wir den Umstieg von Postgres und S3 hinter uns – hier sind die Punkte, die in keiner Kurzanleitung stehen.

Abstrakter Farbverlauf in Indigo und Smaragdgrün

Bindings statt Connection-Strings

Der offensichtlichste Unterschied: Es gibt keine Datenbank-URL mehr. D1 und R2 werden als Bindings in der wrangler.jsonc definiert und stehen dem Worker direkt zur Verfügung. Payload bekommt die Bindings über den Cloudflare-Kontext:

1db: sqliteD1Adapter({ binding: cloudflare.env.D1 }),
2plugins: [
3 r2Storage({
4 bucket: cloudflare.env.R2,
5 collections: { media: { prefix: 'media' } },
6 }),
7],

Lokal emuliert Wrangler beide Ressourcen in .wrangler/state. Für Entwicklung und Tests brauchst du damit weder Docker noch einen gemeinsam genutzten Datenbankserver – jeder Testlauf bekommt seine eigene, wegwerfbare Datenbank.

Migrationen statt Schema-Push

Mit Postgres haben wir in der Entwicklung oft mit automatischem Schema-Push gearbeitet. Mit D1 setzen wir konsequent auf Migrationen: Jede Schemaänderung erzeugt mit payload migrate:create eine Migration, die lokal, in der CI und beim Deployment identisch läuft. Bestehende Postgres-Migrationen lassen sich nicht weiterverwenden – D1 startet mit einer frischen Initial-Migration, alte Inhalte müssen gesondert übernommen werden.

Ein Login-Problem, das nur in Produktion auftrat

Die überraschendste Hürde: Lokal funktionierte der Admin-Login, auf echten Workers kam ein 401. Die Ursache war PBKDF2. Payload hasht Passwörter mit 600.000 Iterationen, die Web-Crypto-Implementierung der Workers lehnt aber mehr als 100.000 Iterationen ab. Das lokale workerd akzeptiert sie – der Fehler war also nur auf Cloudflare selbst reproduzierbar.

Gelöst haben wir das mit einem versionsgebundenen Patch, der nur diesen Fall über @noble/hashes berechnet. Iterationen, Salt und Hash-Format bleiben unverändert, bestehende Passwörter funktionieren weiter. Hintergründe stehen im Payload-Issue #18274.

Bilder: Images Free mit Fallback

Für responsive Bilder nutzt das Template Cloudflare Images über das IMAGES-Binding – bewusst nur im kostenlosen Plan mit 5.000 Transformationen pro Monat. Schlägt eine Transformation fehl, liefert die Seite das Original aus R2 aus. Die Crop- und Fokuspunkt-Funktionen von Sharp entfallen dafür, genau wie im offiziellen D1-Template von Payload.

Fazit

Für Content-Websites und Blogs ist Payload auf D1 eine sehr angenehme Kombination: wenig Infrastruktur, schnelle Auslieferung und ein CMS, das sich nicht nach Kompromiss anfühlt. Testen solltest du aber immer auch auf echten Workers – lokal verhält sich nicht alles gleich.