Cloudflare Workers und WordPress: WooCommerce am Edge ausliefern
Cloudflare Workers führt JavaScript am Rand des globalen Cloudflare-Netzwerks aus. WordPress führt PHP auf einem einzelnen Origin-Server aus. Workers vor WordPress zu setzen ist die Architektur, mit der ein WooCommerce-Shop die Edge-Performance erbt, ohne das CMS umzuschreiben. Die Trade-offs sind real und gehören klar benannt.
Dieser Artikel verankert sich im Pillar Headless-WordPress-Service und ergänzt die Rendering-Entscheidung ISR vs. SSR sowie die Ökonomie von Headless WordPress.
TL;DR
- Workers übernimmt den Read-Path, WordPress übernimmt Schreiboperationen und Authoring.
- WooCommerce-Katalog und Produktdetails rendern am Edge; Warenkorb und Checkout bleiben am Origin.
- Cache-Invalidierung läuft webhook-getrieben, nicht zeitbasiert.
- Cloudflare Pages limitiert die _redirects-Datei auf 2000 Regeln, plane drumherum.
- Der kostenlose Workers-Plan deckelt das komprimierte Bundle bei 1 MB; der bezahlte Plan hebt das an.
Was Cloudflare Workers wirklich ist
Workers ist eine V8-Isolate-Runtime, die JavaScript, TypeScript und WebAssembly innerhalb des Cloudflare-Edge-Netzwerks ausführt (Cloudflares Netzwerk-Seite listet die Rechenzentren). Es ist nicht Node.js, kein Lambda-Container und kein Ort, an dem PHP läuft. WordPress bleibt auf seinem Origin; der Worker ist ein JS-Reverse-Proxy davor.
Ein paar Charakteristika, die definieren, was vor WordPress mit Workers geht und was nicht:
- Kein PHP. Ein Worker kann
wp-load.phpnicht ausführen. Er kann von/wp-json/wp/v2/postsund/wp-json/wc/v3/productslesen, die Antwort transformieren und HTML oder JSON zurückgeben. Jede authentifizierte Mutation übernimmt die WordPress-Installation. - CPU ist das Budget, das zuerst beißt. Der kostenlose Plan erlaubt rund 10 ms CPU pro Request, der bezahlte hebt das Richtung 30 ms an, Unbound geht höher. Eine statisch gerenderte Produktseite, die aus Workers KV liest, kostet nahezu nichts; eine SSR-Template-Schleife, die vier
/wp-json/-Calls aggregiert und die Beschreibung durch Markdown-zu-HTML schickt, sprengt im Free-Plan schnell das Limit. - Zwei Storage-Schichten, zwei Konsistenzmodelle. Workers KV ist eventually consistent und schnell für Edge-Reads; Writes brauchen bis zu einer Minute zur globalen Propagation, und Burst-Writes werden gedrosselt. D1 ist strongly consistent SQLite am Edge. Für WooCommerce ist KV gut für gecachte
/products-Listings; Live-Bestandszähler gehören auf den WordPress-Origin oder in Durable Objects. - Bundle-Größe ist real. Das komprimierte Worker-Skript fährt im Free-Plan bei 1 MB, im bezahlten Plan bei 10 MB. Eine vollständige Astro- oder Next.js-App mit Bildern und Sprach-Bundles braucht den bezahlten Tarif.
- Nachbarprodukte lösen überlappende Probleme. Cloudflare Pages Functions sitzt in derselben Runtime und ist die ergonomisch passende Heimat für eine Astro- oder Next.js-App. Vercel Edge Functions und AWS Lambda@Edge lösen ähnliche Aufgaben mit anderen Kostenmodellen. Workers gewinnt, wenn WordPress bereits hinter Cloudflare-DNS liegt und das Team eine Plattform für Cache, WAF und Rendering will.
Code gegen Web-Platform-APIs (Fetch, Request, Response, Streams, Web Crypto) läuft ohne Anpassung. Code, der auf die Node-Standardbibliothek, native Module oder Dateisystemzugriff setzt, nicht.
Die Zwei-Schichten-Architektur
In einem Workers-+-WordPress-Setup teilen sich zwei Systeme die Verantwortung:
WordPress-Origin. Authoring (Block Editor, REST API, WP-CLI), Schreiboperationen (Beiträge anlegen, aktualisieren, löschen; Bestellanlage; Nutzerregistrierung) und Source of Truth für Inhalte und Produktdaten.
Cloudflare Workers Edge. Rendering des Read-Paths (HTML-Erzeugung), API-Aggregation (Zusammenführung mehrerer WordPress-REST-Endpunkte zu einer Frontend-Antwort), Edge-Caching (pro Route, pro Tag) und übergreifende Belange (Geo-Routing, A/B-Varianten, Header-Rewrites).
Die Grenze ist scharf. Alles, was Zustand verändert, lebt auf dem WordPress-Origin. Alles, was liest, rendert oder aggregiert, kann auf Workers laufen. Warenkorb und Checkout sitzen auf der Grenzlinie, weil sie zustandsbehaftet, aber leselastig sind.
Konkrete WooCommerce-Patterns, die zu Workers wandern
Ein paar Workers-vor-WooCommerce-Patterns, die wir ausgeliefert oder sauber ausgeliefert gesehen haben, mit DACH-spezifischer Würze:
Edge-Cache für /wp-json/-Reads. Eine Worker-Route matcht /wp-json/wc/v3/products* und liefert aus dem Cache, wenn der Cache-Key (URL plus ein kleiner Satz Vary-Header) frisch ist. Bestandskritische Endpunkte wie /wp-json/wc/v3/products/<id> bekommen kürzeres TTL plus Webhook-Invalidierung auf der woocommerce_product_set_stock-Action. Der PHP-Origin hört auf, Produktlisten-Fan-out von Feed-Exportern, Preis-Crawlern und Bot-Traffic zu beantworten. Dasselbe gilt für JTL-Wawi-Inventar-Sync, der über einen Workers-Proxy läuft, der die Bestandsupdates batcht, bevor sie den Origin treffen.
Cart-aware Caching. Die Katalogseite ist gecached, aber das Mini-Cart-Fragment nicht. Der Worker liest das wp_woocommerce_session_*-Cookie, holt das Cart-Fragment vom Origin und stitched die Antwort zusammen. Das Katalog-HTML bleibt cachebar über alle anonymen Nutzer; das Cart-Fragment ist sessionsspezifisch und ungecached. Klarna- oder SOFORT-Callback-Pfade laufen über dieselbe Boundary: Der Worker pinnt die Antwort dynamisch, sodass die Bestätigungsansicht nicht an einer veralteten Cache-Variante hängenbleibt.
Bildtransformation am Edge. WooCommerce-Produktbilder landen in voller Auflösung in der Mediathek. Eine Worker-Route vor /wp-content/uploads/ skaliert, kodiert nach AVIF und cached am Edge. Der Origin lässt Imagick bei jedem ungecachten Request weg, was auf einer ausgelasteten WooCommerce-Maschine eine der lautesten CPU-Quellen ist.
Geo-Redirects und A/B-Varianten. Workers liest cf-ipcountry und schreibt /shop/ für österreichische Besucher auf /shop/at/ um, oder weist ein A/B-Kohorten-Cookie zu und liefert Varianten-HTML, ohne PHP zu treffen. Hier sitzt auch die DSGVO-Consent-Durchsetzung: Der Worker prüft den Consent-Cookie und liefert die Tracking-freie Variante an Besucher, die noch keinen Consent gegeben haben, ohne Origin-Roundtrip. Wer Cloudflare im AVV-Setup einsetzt, schaltet den DPA auf EU-only, sonst hält der AVV juristisch nicht.
Custom-WAF-Regeln über das WAF-Pro-Standardset hinaus. POST auf /xmlrpc.php blocken, /?s=-Suchanfragen aus einer einzelnen ASN ratelimiten, Requests mit wp-config im Pfad droppen. Workers liefert eine programmierbare Schicht über dem Managed WAF, ohne Enterprise-Rule-Slots zu zahlen.
Was auf dem WordPress-Origin bleibt: Block-Editor-Speichervorgänge, Bestellanlage aus authentifiziertem Checkout, Payment-Gateway-Callbacks (Klarna, SOFORT, SEPA-Lastschrift), Admin-Sessions und der Webhook-Fan-out, der die Cache-Invalidierung am Worker auslöst. Der PHP-Server skaliert auf Redaktionsvolumen plus Bestellvolumen, nicht auf anonymen Katalog-Traffic.
Wo die Grenze ziehen
Drei Routenkategorien, drei verschiedene Rendering-Regeln:
Statisch oder ISR am Edge. Marketing-Seiten, Blogposts, Kategorienarchive, Produktdetailseiten. Aggressiv gecached mit webhook-getriebener Invalidierung.
SSR am Edge ohne Cache. Warenkorb, Konto, Dashboards, Checkout-Seiten, die personalisiert und session-getrieben sind. Workers führt das Rendering bei jedem Request aus; WordPress liefert die Daten via REST.
Nur Origin, kein Worker. WP-Admin (/wp-admin/), der Block Editor und WordPress-Core-REST-Endpunkte für interne Authoring-Zwecke. Die Workers-Routenkonfiguration schließt diese explizit aus der Edge-Schicht aus.
Der häufige Fehler: den Warenkorb in den Edge-Cache verschieben zu wollen. Der Warenkorb ist nutzerspezifischer Zustand; ihn nutzerübergreifend zu cachen ist ein Sicherheitsvorfall mit Anlauf. SSR am Edge ist das richtige Modell: Der Worker rendert das HTML für den Warenkorb dieses Nutzers, cached aber das Ergebnis nicht.
Cache-Invalidierung, das tragende Element
ISR am Edge ist nur dann korrekt, wenn die Invalidierung korrekt ist. Das Muster, das funktioniert:
Tagge jede gecachte Antwort. Jede gerenderte Seite wird mit den WordPress-Post-IDs, Term-IDs und Produkt-IDs getaggt, auf die sie verweist. Der Workers-Cache unterstützt tag-basiertes Purging über die Cache-API.
Webhook bei jedem WordPress-Schreibvorgang. Veröffentlichung, Slug-Änderung, Beitragslöschung, Bestandsupdate, Preisänderung. Jede dieser Aktionen feuert einen Webhook auf eine Workers-Route, die “Post 8421 hat sich geändert” in “purge tag wp-post-8421” über die Cloudflare-API übersetzt.
Zeitbasierte Revalidierung nur als Absicherung. Ein Stale-While-Revalidate-Fenster von 1 Stunde fängt Webhook-Zustellfehler ab. Es ist nicht der Hauptmechanismus. Eine Site, die alle 60 Sekunden revalidiert, baut jede Seite 60 Mal pro Stunde neu; bei 5000 Seiten sind das 300000 unnötige Renderings.
Die Reihenfolge zählt: erst invalidieren, dann schreiben. Wenn ein WordPress-Publish den Webhook auslöst, invalidiert der Worker den Tag, und der nächste Request rebaut die Seite vom jetzt aktuellen Origin. In umgekehrter Reihenfolge schleicht sich ein veralteter Render in den Cache und bleibt dort bis zur nächsten Invalidierung.
Limits, um die herum geplant werden muss
Dokumentierte Plattformlimits von Cloudflare:
_redirects-Limit auf Cloudflare Pages: 2000 Regeln. Darüber schlagen Deploys fehl. Wir tracken das in der Build-Pipeline und liegen aktuell bei 1600.- Worker-Bundle-Größe: 1 MB komprimiert im kostenlosen Plan, mehr in bezahlten Plänen. Routen, die vollständige Astro- oder Next.js-Anwendungen ausliefern, brauchen den bezahlten Plan.
- CPU-Zeit pro Request: 10 ms im kostenlosen Plan, 50 ms oder mehr in bezahlten. SSR mit schwerer Template-Logik überschreitet die Free-Plan-Decke schnell; ISR-gecachte Antworten verbrauchen praktisch keine CPU.
- Subrequests pro Request: 50 im kostenlosen Plan, mehr in bezahlten. WordPress-REST-Aggregation, die auf mehrere Endpunkte fächert, läuft auf komplexen Seiten in dieses Limit.
Die übliche architektonische Antwort: für den bezahlten Plan designen, auf dem bezahlten Plan ausliefern, den kostenlosen Plan als Entwicklungs-Sandbox behandeln.
Fehlerbilder, die vor dem Go-Live klar sein sollten
Ein paar konkrete Wege, wie wir ein Workers-+-WordPress-Setup brechen oder das Team überraschen sehen:
KV-Write-Throttling bei stoßweiser Invalidierung. Ein Bulk-Produktimport, der 5000 SKUs anfasst, feuert 5000 woocommerce_update_product-Webhooks. Der Worker übersetzt jeden in einen KV-Write auf einen Cache-Key pro SKU. Der KV-Write-Durchsatz ist pro Namespace ratelimited, also queuen Writes und der Cache bleibt minutenlang stale. Die Lösung ist Debouncing auf WordPress-Seite und gebatchte Invalidierungen, oder die Per-SKU-Map durch einen einzelnen Tag-Purge gegen die Cloudflare-Cache-API zu ersetzen. Wer einen JTL-Wawi-Sync laufen lässt, der nachts zehntausende Bestandsupdates durchpumpt, sieht diesen Effekt zuerst.
Cold-Start vs. Warm-Start auf trafficarmen Locales. Ein V8-Isolate, der zwischen Requests wiederverwendet wird, kostet praktisch keine Startzeit. Der erste Request in eine Region nach längerer Idle-Phase zahlt zusätzliche 5 bis 50 ms, während das Isolate hochfährt und das Skript geparst wird. Auf einer schwach besuchten DACH-Sublocale (etwa /at/ oder /ch/) sieht p99 schlechter aus als p50. Synthetische Monitore aus vielen Locations verschmieren das; RUM zeigt es ungeschönt.
Die 1-MB-Bundle-Decke im Free-Plan. Eine vollständige Next.js-15-App mit Cloudflare-Adapter, react-server-dom, ein paar Sprach-Bundles und dem WooCommerce-REST-Client knackt 1 MB komprimiert mit Leichtigkeit. Der Deploy schlägt beim Upload fehl, nicht zur Laufzeit. Plane für Paid (10 MB) oder splitte das Rendering auf mehrere Worker-Skripte.
Subrequest-Fan-out auf aggregierten Seiten. Eine Kategorieseite, die Term, Produkte, verwandte Kategorien, Breadcrumbs und Menü holt, trifft fünf /wp-json/-Endpunkte. Free-Plan deckelt Subrequests bei 50 pro Worker-Invocation, Paid bei 1000. Aggregations-Layer, die die Antwort WordPress-seitig vorkomponieren, oder ein einzelner GraphQL-Endpunkt via WPGraphQL halten den Zähler vorhersehbar.
Webhook-Zustellfehler hinterlassen Stale Cache. WordPress feuert den Webhook in der shutdown-Action; wenn der PHP-FPM-Worker timeoutet oder das Netz wegbricht, erreicht der Webhook den Worker nie. Bei Klarna-Refund- oder SEPA-Reversal-Webhooks, deren Zustellung beim Provider verzögert ist, heißt fehlende Absicherung, dass die Produktseite “verfügbar” zeigt, obwohl der Refund den Bestand erhöht hat. Tag-basiertes Stale-While-Revalidate von 1 Stunde fängt das ab; ohne Backstop bleibt der Stale Render bis zum nächsten manuellen Purge im Cache.
Astro- und Next.js-Kompatibilität
Laut aktuelle Tech-Radar-Meinung liefern sowohl Astro 5+ als auch Next.js 15 offizielle Cloudflare-Adapter. Der Astro-Adapter kompiliert die statischen + SSR-Routen zu Workers; der Next.js-Adapter macht dasselbe mit dem App Router. Beide produzieren ein Deploy-Artefakt, das auf Cloudflare Pages mit Workers darunter läuft.
Die Auswahl zwischen beiden behandelt die Entscheidungsmatrix Next.js vs. Astro. Für einen content-lastigen WooCommerce-Shop ist Astro meist die richtige Standardwahl, weil das Static-First-Modell sauber auf den Katalog passt. Für ein anwendungslastigeres Setup (Konto, Dashboard, komplexe Personalisierung) hat das Server-Components-Modell von Next.js den ergonomischen Vorteil.
So oder so: der WordPress-Origin bleibt unverändert. Workers + WordPress ist ein Architekturmuster, keine Framework-Entscheidung.
Wie das Agentur-Engagement aussieht
Eine Workers-+-WordPress-Migration im Headless-WordPress-Service von WPPoland läuft in vier Phasen.
Phase eins, Audit. Inventarisierung der WordPress-Installation (Plugins, Custom Code, REST-API-Surface, Anzahl Admin-Nutzer), Messung von Baseline-TTFB und TTI, Identifikation von allem, was auf PHP-Rendering zur Request-Zeit setzt (Theme-Funktionen, Page Builder, serverseitige Personalisierung).
Phase zwei, REST- und Webhook-Scaffolding. Hinzufügen oder Härten der WordPress-REST-Endpunkte, die das Frontend braucht. Aufsetzen der Webhook-Auslöser für Veröffentlichung, Slug-Änderung und (im Commerce-Fall) Bestandsänderung. Verifikation der Webhook-Zustellung auf einer Staging-Domain.
Phase drei, Frontend-Build und Cutover. Bau des Astro- oder Next.js-Frontends, Deployment auf Cloudflare Pages, Parallelbetrieb mit dem Legacy-Frontend für ein Messfenster, dann Umschaltung via DNS oder Cloudflare-Proxy. Sitemap- und Canonical-URL-Handling gemäß unserer SEO-Pattern-Checkliste ist nicht verhandelbar.
Phase vier, Observability und Tuning. Edge-Logs (Cloudflare Logpush), Origin-Logs (der WordPress-Server) und synthetische Tests. Tuning der Cache-TTLs und Tag-Invalidierungsmuster anhand des Live-Traffic-Profils.
Wir versprechen keine konkreten Zahlen im Voraus, weil TTFB und TTI vom Plugin-Payload des WordPress-Origins, vom Frontend-Framework und vom Netzwerk des Nutzers abhängen. Was wir veröffentlichen sind Protokolle und durchgeführte Messungen: siehe unser Benchmark-Scaffold für die Methodik, an die wir uns halten.
Wo das hingehört
Dieser Pillar-Artikel verankert sich im Cluster Headless-WordPress-Service. Für die Framework-Wahl siehe die Entscheidungsmatrix Next.js vs. Astro. Für die Rendering-Wahl pro Route siehe die Entscheidung ISR vs. SSR. Für SEO-Migrationsrisiken siehe die Headless-WordPress-SEO-Pattern-Checkliste. Für die Kostensicht siehe die Ökonomie von Headless WordPress 2026.
