Zwei Systeme, zwei Wahrheiten: warum die Trennung richtig ist
Das Muster begegnet mir in fast jedem Gespräch mit Herstellern und Händlern: Die Produktdaten leben im ERP oder PIM, etwa in SAP Business One oder Akeneo. Das Marketing will Landingpages, Ratgeber und Kampagnen bauen. Und irgendjemand schlägt vor, dafür «einfach alles ins CMS zu kopieren». Genau an diesem Vorschlag scheitern später die meisten Projekte: Die Kopie veraltet, die Pflege verdoppelt sich, und am Ende weiß niemand, welcher Preis stimmt.
Zur Einordnung, wer hier schreibt: Ich bin Matthias, Ein-Personen-Agentur happycoding.agency in Berlin. Ich baue Websites und Portale auf Sanity und verbinde sie mit den Systemen, die bei meinen Kunden bereits laufen. Was Sanity grundsätzlich ist und wie der Content Lake arbeitet, erkläre ich im Grundlagenartikel Was ist Sanity?.
In diesem Artikel bekommst du die Architektur, die sich in meinen Projekten bewährt hat: eine klare Datenhoheit je Datenart, drei Sync-Patterns zwischen ERP, PIM und Sanity, die typischen Fallstricke aus dem Betrieb und eine Entscheidungshilfe, wann du überhaupt ein PIM brauchst.
Single Source of Truth: jede Datenart hat genau ein führendes System
Vorab das Grundprinzip: Für jede Datenart gibt es genau eine Quelle der Wahrheit, englisch Single Source of Truth. Alle anderen Systeme halten höchstens Kopien, und jede Kopie weiß, dass sie Kopie ist. Sobald zwei Systeme dasselbe Feld führen dürfen, hast du keinen Datenbestand mehr, sondern zwei Meinungen.
So teile ich die Zuständigkeiten in Projekten mit Herstellern und Händlern auf:
| Datenart | Führendes System | Beispiele |
|---|---|---|
| Stammdaten, Preise, Bestände | ERP | Artikelnummern, Konditionen, Lagerbestand |
| Attribute, Varianten, Übersetzungen | PIM | technische Daten, Klassifikation nach ETIM oder ECLASS |
| Redaktioneller Content | Sanity | Landingpages, Ratgeber, Markenwelt, SEO-Texte |
| Transaktionen | Shop oder ERP | Warenkorb, Bestellung, Rechnung |
Das gilt branchenübergreifend. Beim Autohändler kommen die Fahrzeugdaten aus dem Händlersystem und wandern per Feed zu den Fahrzeugbörsen; die Ratgeberseite «Warum ein Jahreswagen?» gehört ins CMS. Beim technischen Großhändler pflegt das PIM 40.000 Artikel mit ETIM-Attributen; die Anwendungsberichte und Auswahlhilfen entstehen in Sanity.
Daraus folgt die wichtigste Regel dieses Artikels: Ins CMS gehört nur, was Redakteure verantworten. Drei Dinge haben in Sanity nichts verloren, auch nicht «zur Sicherheit» als Kopie:
- Preise: Sie ändern sich nach ERP-Logik, zuweilen je Kunde. Eine Kopie im CMS ist im Zweifel falsch.
- Bestände: Sie veralten im Minutentakt. Kein Sync-Intervall ist kurz genug, wenn die Website Verfügbarkeit verspricht.
- Attributlogik: Vererbung, Varianten und Klassifikation sind Kernaufgaben des PIM. Im CMS nachgebaut werden sie zur zweiten, schlechteren Implementierung.
Der Gegencheck funktioniert genauso: Was im CMS gepflegt wird, darf kein anderes System überschreiben. Die Marketingbeschreibung eines Produkts kann deshalb bewusst in Sanity liegen, während die technische Beschreibung aus dem PIM kommt. Zwei Felder, zwei Eigentümer, kein Konflikt.
Drei Sync-Patterns zwischen ERP, PIM und Content Lake
Zum Kern: Wie kommen die Systeme zusammen, ohne dass Daten doppelt gepflegt werden? Drei Patterns decken in meiner Praxis fast alle Fälle ab. Welches passt, hängt davon ab, wie aktuell die Daten auf der Website sein müssen und ob Redakteure mit ihnen arbeiten sollen.
Pattern 1: Webhook-Push in den Content Lake
Das PIM meldet Änderungen, ein kleiner Dienst schreibt sie nach Sanity. Akeneo bringt dafür die Event Platform mit: Du abonnierst Produkt-Events, statt die API im Takt abzufragen. Die ältere Events API ist abgekündigt und wird nur noch bis zum 31.12.2026 unterstützt (Stand: Oktober 2026).
Auf der Sanity-Seite nimmt die Mutations-API die Daten entgegen. Der entscheidende Kniff ist eine deterministische Dokument-ID, etwa produkt-{SKU}: Mit der Mutation createOrReplace aktualisiert jeder Sync dasselbe Dokument, statt Dubletten anzulegen. Eine Transaktion fasst mehrere Mutationen zusammen, sodass ein Produktupdate ganz oder gar nicht ankommt.
Bei Massenimporten lohnt ein Blick auf die Grenzen: Eine query-basierte Mutation fasst höchstens 10.000 Dokumente an, größere Bestände paginierst du über die _id. Für den nächtlichen Vollabgleich von 40.000 Artikeln heißt das: mehrere Transaktionen, idealerweise mit eigener transactionId, damit du im Fehlerfall nachvollziehen kannst, welcher Batch durchging.
Dieses Pattern wählst du, wenn Redakteure in Sanity mit Produktdaten arbeiten sollen: Sie sehen Titel und Attribute im Studio, referenzieren Produkte in Landingpages, und die synchronisierten Felder sind schreibgeschützt, weil das PIM sie führt.
Pattern 2: Pull zur Build- oder Anfragezeit
Die Gegenrichtung: Sanity speichert gar keine Produktdaten. Dein Frontend fragt beide APIs ab und fügt die Antworten zur Seite zusammen, beim statischen Build oder live pro Anfrage. Preise und Bestände würde ich ausnahmslos so behandeln: live vom ERP-Endpunkt, nie aus einer Kopie.
Beim Pull lohnt ein Blick aufs Caching: Sanitys API-CDN beantwortet GROQ-Abfragen aus dem Cache und entlastet Build und Laufzeit. Für redaktionellen Content ist das ideal. Den Preis aus dem ERP holst du dagegen bewusst am Cache vorbei, sonst handelst du dir die Veraltung durch die Hintertür wieder ein.
Der Preis dieses Patterns: Redakteure sehen die Produkte nicht im Studio. Für einen Katalog mit stündlich wechselnden Beständen ist das egal, für kuratierte Landingpages ist es ein echter Verlust. Deshalb kombiniere ich Pattern 2 meist mit dem dritten.
Pattern 3: Referenz auf externe IDs statt Datenkopie
Das Sanity-Dokument speichert nur den Schlüssel, etwa die SKU, und das Frontend löst ihn zur Laufzeit gegen ERP oder PIM auf. In der Praxis hat sich ein Mittelweg bewährt: ein schlanker Produkt-Stub in Sanity mit ID, Name und Bild, alles andere bleibt draußen. Im Schema ist der Stub ein eigener Dokumenttyp mit readOnly-Feldern und der SKU als Pflichtfeld.
Redakteure referenzieren den Stub wie jedes andere Dokument, die Wahrheit bleibt im Quellsystem. Du bekommst damit beides: kuratierbare Produktplatzierungen im Studio und aktuelle Daten auf der Website, ohne den vollen Attributbestand zu kopieren.
Auch die Gegenrichtung ist abgedeckt: Sanitys GROQ-powered Webhooks feuern bei create, update und delete, mit GROQ-Filter und frei definierter Payload. Die Zustellung ist at-least-once mit Idempotency-Key, zwei Wiederholungen im 30-Sekunden-Abstand, Timeout nach 30 Sekunden (Stand: Oktober 2026). Sichere den Empfänger über das Webhook-Secret ab; Sanity signiert nach demselben Verfahren wie Stripe.
Wenn du für die Sync-Logik keinen eigenen Server betreiben willst: Sanity Functions führen deinen Code direkt auf Sanitys Infrastruktur aus, ausgelöst durch Dokument-Events und gefiltert per GROQ. Eine Function läuft standardmäßig bis zu 10 Sekunden, konfigurierbar bis 900 Sekunden (Stand: Oktober 2026). Für schlanke Sync-Aufgaben reicht das; einen ausgewachsenen Nachtimport betreibe ich weiterhin als eigenen Job.
Das Prinzip ist übrigens nicht Sanity-exklusiv: Dieselbe Integrationsfrage habe ich für die WordPress-Welt im Artikel WordPress mit CRM, ERP und PIM verbinden beantwortet. Der Unterschied liegt im Werkzeugkasten, nicht in der Architektur.
Drei Fallstricke aus meiner Projektpraxis
Die Patterns sind schnell erklärt, die Fehler stecken im Betrieb. Die folgenden drei Punkte stammen aus meiner happycoding-Projektarbeit; ich beschreibe sie als Szenarien ohne Kundennamen, denn die Muster wiederholen sich quer durch die Branchen.
Sync-Konflikte: zwei Schreiber, ein Feld
Das Szenario: Der Sync schreibt die Produktbeschreibung aus dem PIM, eine Redakteurin verbessert sie abends im Studio, der nächtliche Sync überschreibt ihre Arbeit kommentarlos. Niemand merkt es, bis sich jemand beschwert.
Die Lösung ist Felderhoheit statt Hoffnung: Jedes Feld im Schema gehört entweder der Maschine oder dem Menschen, nie beiden. Maschinenfelder markierst du im Studio als readOnly, redaktionelle Felder fasst der Sync grundsätzlich nicht an. Technisch heißt das: gezielte patch-Mutationen auf die Maschinenfelder statt createOrReplace aufs ganze Dokument.
Lösch-Propagation: das Produkt ist weg, die Referenz nicht
Das Szenario: Ein Artikel fliegt aus dem Sortiment, das PIM löscht ihn, aber fünf Landingpages in Sanity referenzieren ihn noch. Sanity verweigert das Löschen eines Dokuments, auf das starke Referenzen zeigen; dein Sync-Dienst bricht mit einem Fehler ab, und ab da verarbeitet er gar nichts mehr.
Mein Vorgehen: Produkt-Stubs nicht löschen, sondern auf einen Status wie «ausgelaufen» setzen. Das Frontend blendet sie aus, Redakteure sehen im Studio, warum eine Seite ein Loch hat, und räumen die Referenzen in Ruhe auf. Und plane die eigene Webhook-Konfiguration bewusst: Auch das Unpublishen eines Dokuments feuert den delete-Trigger.
Preis-Aktualität: die teuerste Kopie
Das Szenario: Preise wurden «der Einfachheit halber» mit in den Content Lake synchronisiert. Dann ändert das ERP die Konditionen, der Sync hängt zwei Stunden, und die Website verkauft zum alten Preis. Im B2B mit kundenindividuellen Konditionen ist das mehr als peinlich, da steht ein Vertrauensverlust im Raum.
Darum wiederhole ich die Regel aus dem ersten Abschnitt als Merksatz: Ein Preis im CMS ist kein Preis, sondern ein Gerücht. Preise und Bestände holt das Frontend zur Anfragezeit vom ERP-Endpunkt; wo die Last das nicht erlaubt, hilft ein kurzlebiger Cache von wenigen Minuten mit sichtbarem Zeitstempel.
Entscheidungshilfe: wann PIM plus Sanity, wann Sanity allein?
Bleibt die Frage, ob du die Doppelarchitektur überhaupt brauchst. Drei Signale sprechen in meinen Projektgesprächen für ein PIM: mehr als ein Ausgabekanal, ein Team, das Attribute als eigenen Arbeitsschritt pflegt, und Handelspartner, die Klassifikationen wie ETIM verlangen. Fehlen alle drei, spare dir das System.
| Situation | Empfehlung |
|---|---|
| Unter rund 500 Produkten, eine Website als einziger Kanal | Sanity allein, Produkte als eigener Dokumenttyp |
| Produktdaten gehen an Website, Shop, Marktplätze und Print | PIM führt, Sanity ergänzt den Content (Pattern 1 oder 3) |
| ERP vorhanden, aber keine eigene Attributpflege | ERP und Sanity direkt verbinden, ohne PIM dazwischen |
| Shop mit eigener Produktverwaltung, etwa MedusaJS | Shop führt die Produktdaten, Sanity liefert das Storytelling |
| Preise und Bestände auf der Website | immer live aus ERP oder Shop, nie aus dem CMS |
Die erste Zeile unterschätzen viele: Sanity kann Produktdaten vollwertig halten, mit Validierung, Varianten als Objekten und GROQ als Abfragesprache. Solange nur die Website die Daten braucht und ein kleines Team sie pflegt, wäre ein PIM zusätzliche Infrastruktur ohne Auftrag.
Die vierte Zeile habe ich für Shop-Projekte im Detail durchgespielt: Im Leitfaden MedusaJS und Headless CMS kombinieren findest du dieselbe Architekturfrage aus der E-Commerce-Perspektive, inklusive der Frage, wer die Produktseite rendert.
Nächste Schritte
Wenn du gerade vor dieser Architekturentscheidung stehst, beantworte drei Fragen: Welche Datenart hat heute kein eindeutig führendes System? Wie aktuell müssen Preise auf der Website sein? Und wer soll Produktinhalte künftig pflegen? Mit diesen Antworten steht das Grundgerüst fast von selbst. Wie ich Sanity-Projekte plane und umsetze, zeigt dir meine Sanity-Leistungsseite.
Du willst die Antworten nicht allein sortieren? Schick mir deine Systemlandschaft, und ich skizziere dir im Gespräch, welches Pattern zu ihr passt und wo die Fallstricke liegen: Buch dir ein unverbindliches Erstgespräch.
