Next.js Caching für Shopware Headless: ISR, On-Demand-Revalidation und der Warenkorb
Headless Shopware liefert schöne LCP-Werte — bis jemand im Backend einen Preis ändert und drei Stunden später noch der alte Wert im Frontend hängt. Oder bis der Warenkorb plötzlich Artikel eines anderen Kunden zeigt, weil die Page versehentlich statisch gecacht wurde. Caching in Next.js ist mächtig, aber es bestraft Halbwissen. Wie du Produktseiten schnell auslieferst, Preisänderungen sekundengenau einspielst und den Warenkorb sauber dynamisch hältst — ohne dass dir der Cache irgendwann das Vertrauen kostet.
1. Die drei Datenklassen, die du sauber trennen musst
Bevor man eine Zeile Caching-Code schreibt, lohnt sich eine ehrliche Inventur der Daten, die das Frontend von Shopware bekommt. In der Praxis lassen sie sich in drei Klassen sortieren: statische Inhalte (Kategoriestruktur, CMS-Seiten, Footer-Navigation), semi-dynamische Daten (Produktpreise, Lagerbestände, Verfügbarkeiten) und vollständig nutzerspezifische Daten (Warenkorb, Kundenpreise, Wunschliste, Session). Jede dieser Klassen braucht eine andere Caching-Strategie. Wer alles in einen Topf wirft, landet entweder bei einem schnellen, aber falschen Shop — oder bei einem korrekten, aber langsamen.
Die meisten Performance-Probleme in Headless-Setups entstehen genau hier: Entwickler bauen entweder konsequent SSR (alles korrekt, alles langsam) oder kippen versehentlich nutzerspezifische Daten in die statische Generierung. Beides ist vermeidbar, wenn die Datenklassen früh festgelegt sind.
2. ISR für Produkt- und Kategorieseiten
Produkt- und Kategorieseiten sind die offensichtlichen Kandidaten für Incremental Static Regeneration. Sie sind für alle Besucher identisch (sofern keine Kundenpreise gelten), werden häufig aufgerufen und ändern sich verhältnismäßig selten. In Next.js 14+ steuert man das im App Router über die Route-Segment-Optionen — etwa export const revalidate = 3600 auf der Produktseite. Damit serviert Next.js eine vorgerenderte HTML-Version aus dem Cache und regeneriert sie im Hintergrund nach Ablauf der Frist.
In der Praxis hat sich bewährt, das revalidate-Intervall großzügig zu setzen (eine Stunde, ein Tag) und Änderungen aktiv per On-Demand-Revalidation einzuspielen. So bleibt der TTFB minimal, und der Cache reagiert trotzdem zeitnah auf echte Datenänderungen aus Shopware.
3. On-Demand-Revalidation über Shopware-Webhooks
Wenn ein Redakteur im Shopware-Backend einen Preis ändert oder ein Produkt aktiv schaltet, soll das Frontend das innerhalb von Sekunden mitbekommen — nicht erst nach dem nächsten ISR-Intervall. Der saubere Weg führt über Shopwares Webhook-System: ein App-Webhook auf Events wie product.written oder category.written ruft eine Next.js Route Handler-Endpoint auf, die revalidatePath() oder revalidateTag() aufruft. Die vollständige Liste verfügbarer Events findet sich in der Webhook Event Reference.
Der entscheidende Detail-Punkt: Tags. Wenn jeder fetch()-Aufruf zur Store API mit einem next.tags: [`product-${id}`] versehen wird, kann der Webhook gezielt nur die betroffene Produktseite invalidieren — statt einen ganzen Pfad oder gar den gesamten Cache zu kippen. Das spart in Shops mit hoher Aktualisierungsfrequenz spürbar Origin-Last und schützt vor Cache-Stampedes nach Bulk-Imports.
4. Warum der Warenkorb nie gecacht werden darf
Der Warenkorb ist die gefährlichste Stelle in jedem Headless-Setup. Er ist nutzerspezifisch, ändert sich permanent und enthält im B2B-Kontext oft auch Kundenpreise und Verfügbarkeiten, die nicht in Logs auftauchen sollten. Trotzdem rutscht er regelmäßig in den Cache, weil Entwickler die Daten aus Bequemlichkeit in einer Server Component holen, die nicht explizit als dynamisch markiert ist.
Die saubere Lösung: Warenkorb- und Account-Daten konsequent client-seitig laden (zum Beispiel über SWR oder TanStack Query), oder in Server Components mit fetch(url, { cache: "no-store" }) arbeiten. Wer den App Router nutzt, sollte zusätzlich export const dynamic = "force-dynamic" auf Account-Routen setzen, um versehentliches Static Rendering im Build auszuschließen. Das ist eine dieser scheinbar überflüssigen Doppelabsicherungen, die in einem späteren Refactoring die Karriere rettet.
5. Der sw-context-token und seine Tücken
Jede Shopware Store API-Anfrage trägt einen sw-context-token, der die Session des Kunden identifiziert. Wenn dieser Token versehentlich in den Cache-Key eines Next.js-Fetches einfließt, hast du pro Besucher einen eigenen Cache-Eintrag — der Cache läuft heiß, hilft aber niemandem. Umgekehrt: Wenn du den Token für eine Warenkorb-Anfrage weglässt, holt sich Next.js bei jedem Besucher denselben (leeren) Warenkorb aus dem Cache.
Faustregel: Für anonyme Daten (Produktlisten, Kategorien) den Token weglassen oder einen geteilten Sales-Channel-Token verwenden. Für nutzerspezifische Daten den Token mitschicken und gleichzeitig cache: "no-store" setzen. Die zwei Welten dürfen sich im Code nicht vermischen — sonst entstehen subtile Bugs, die erst auffallen, wenn Kunde A plötzlich den Warenkorb von Kunde B sieht.
6. Monitoring: Was du wirklich messen solltest
Caching ohne Monitoring ist Schätzen mit Stil. Drei Metriken haben sich in produktiven Setups als wirklich aussagekräftig erwiesen: die Hit-Rate des Next.js Data Cache (über die Build-Logs und das x-vercel-cache-Header oder den eigenen CDN-Header), die Origin-Anfragen an die Shopware Store API (idealerweise mit Datadog oder einem APM mit URL-Aggregation) und die Zeit zwischen Backend-Änderung und sichtbarer Aktualisierung im Frontend (manuell testen oder per Synthetic Monitor).
Die spannendsten Erkenntnisse kommen meist aus der dritten Metrik: viele Shops cachen aggressiv genug, dass Preisänderungen erst durch den nächsten Build sichtbar werden. Das ist akzeptabel für einen Blog, aber für einen B2B-Shop mit dynamischen Vertragspreisen ein Geschäftsrisiko.
7. Fazit: Caching ist eine Architekturentscheidung
Caching in Headless Shopware ist kein Performance-Feature, das man am Ende des Projekts draufschraubt — es ist eine Architekturentscheidung, die früh getroffen werden muss. Wer die Datenklassen sauber trennt, ISR auf Produktseiten kombiniert mit Webhook-getriebener Revalidation, und nutzerspezifische Daten konsequent vom Cache fernhält, bekommt einen Shop, der schnell ist und gleichzeitig vertrauenswürdig. Beides gleichzeitig — und nicht eines auf Kosten des anderen.
Du baust gerade Headless Shopware mit Next.js und kämpfst mit dem Caching?
Lass uns in 30 Minuten gemeinsam auf deine Architektur schauen — wo die Datenklassen sauber sind und wo der Cache dich überrumpeln wird. Kein Sales-Call.