Jedem SaaS-Kunden seinen eigenen Content-Space geben
Geben Sie jedem Kunden einen isolierten Content-Space, mit Isolation, die durch PostgreSQL Row-Level Security durchgesetzt wird — nicht durch ein if-Statement auf Anwendungsebene.
Irgendwo zwischen Kunde zwanzig und Kunde fünfzig hört „wir fügen einfach eine tenant_id-Spalte hinzu“ auf, ein Plan zu sein, und wird zu einer Belastung.
In diesem Artikel geht es um die drei Wege, mandantenfähige Inhalte umzusetzen, warum einer davon deutlich sicherer ist, und was die gängigen CMS-Preismodelle mit einer SaaS-Marge machen, wenn die Kundenzahl wächst.
Fast alle landen bei der Zeilenebene, weil die Betriebskosten der anderen beiden real sind und sich aufsummieren. Was die letzte Zelle zur ganzen Frage macht: Was stoppt die Abfrage, die den Filter vergisst?
Nicht weil Ihr Team nachlässig ist. Wegen der Arithmetik.
Ein ausgereiftes Produkt hat Hunderte von Abfragen. Einige stecken im Reporting-Job, den seit einem Jahr niemand geöffnet hat. Einige stecken im Admin-Tool, das während eines Incidents geschrieben wurde. Einige stecken in einem Modul, das ein externer Dienstleister hinzugefügt und ein Reviewer nur überflogen hat. Jede einzelne davon muss sich an WHERE tenant_id = $1 erinnern.
Der Fehler ist stumm und total. Ein fehlender Filter wirft keine Ausnahme. Er gibt die Inhalte eines Kunden an einen anderen zurück, in einer Antwort, die völlig normal aussieht, bis jemand die unveröffentlichte Preisseite seines Wettbewerbers in einem Dropdown bemerkt.
PostgreSQL Row-Level Security verschiebt die Grenze unter den Fehler. Sie hängen eine Richtlinie an die Tabelle, setzen den Mandanten in der Sitzung, und die Datenbank wendet das Prädikat auf jede Abfrage an — auch auf die, die niemand geprüft hat:
Jetzt gibt die Abfrage, die den Filter vergessen hat, null Zeilen zurück statt der aller anderen. Der Bug wird zu einer sichtbaren Abwesenheit statt zu einem unsichtbaren Leck — und dieser Unterschied ist das ganze Argument.
corpusctl macht das im Kern, neben Auth und der Modul-Registry. Jede Anwendungsabfrage ist weiterhin explizit mandantenbezogen; RLS ist die zweite Verteidigungslinie, nicht die erste. Der Sinn einer zweiten Linie ist, dass sie an dem Tag da ist, an dem die erste versagt.
Tabellen sind außerdem nach Mandant hash-partitioniert, was verhindert, dass ein großer Kunde die Abfragepläne für alle anderen verschlechtert.
Der Modellierungsfehler, der später am meisten kostet.
In einem echten SaaS gehören Menschen zu mehreren Kunden. Ein Agenturnutzer verwaltet drei Ihrer Kunden. Ein Support-Ingenieur braucht eine Woche lang Lesezugriff auf ein Konto. Ein externer Dienstleister arbeitet an Marke zwei und darf Marke eins nicht sehen.
Wenn Ihr Modell „Nutzer gehört zu Mandant“ lautet, wird jeder dieser Fälle zu einem doppelten Konto, und doppelte Konten werden zu einem Audit-Problem.
corpusctls Modell: Ein Nutzer trägt in jedem Space eine separate Rolle. Eigentümer im einen, Redakteur im anderen, unsichtbar im dritten. Eine Identität, N Mitgliedschaften, und das Panel zeigt nur die Spaces, zu denen die Person tatsächlich gehört.
Darüber steht eine bewusste Regel: Der letzte Eigentümer eines Space kann nicht herabgestuft oder entfernt werden. Ein Space ohne Eigentümer ist ein Space, den niemand verwalten kann — das Schloss bleibt außen.
#Was projektbasierte Preise mit einer SaaS-Marge machen
Hier hört die CMS-Wahl auf, eine technische Entscheidung zu sein.
Verifiziert anhand der Preisseiten der Anbieter am 17. August 2026:
Produkt
Einheit
Preis
100 Kunden
Strapi Cloud
Pro Projekt
ab 35 $/Monat
ab 3.500 $/Monat
Sanity
Pro Dataset über 2
999 $/Monat
untragbar
Directus
Pro Instanz / Sitz
499 $/Monat Team, +50 $/Sitz
Betrieb pro Instanz
Ghost(Pro)
Pro Publikation, publikumsskaliert
ab 18 $/Monat jährlich
100 Abonnements
corpusctl
Keine
Pauschaltarif
unverändert
Das erkennbare Muster: Diese Einheiten skalieren mit Ihrer Kundenzahl, nicht mit Ihrem Umsatz pro Kunde. Ein SaaS mit einem 29-$/Monat-Tarif kann keine 35-$/Monat-CMS-Position pro Kunde verkraften. Die Arithmetik geht schlicht nicht auf, und mit dem Volumen wird sie nicht besser.
Das ist der Fall, für den corpusctl gebaut wurde. Spaces sind keine Abrechnungseinheit.
#Lesezugriffe, und warum auch sie nicht abgemessen werden sollten
Der zweite Kostenfaktor, der mit den Kunden skaliert, ist Traffic. Wenn Ihr CMS API-Aufrufe abmisst, dann liegen die Besucher jedes Kunden auf Ihrem Zähler, und Ihr verkehrsreichster Kunde ist Ihr teuerster — unabhängig davon, was er Ihnen zahlt.
corpusctls Lesepfad entfernt den Zähler, indem er den Aufruf entfernt. Beim Veröffentlichen wird der Inhalt in eine unveränderliche, hash-adressierte Datei im Objektspeicher geschrieben und ein Manifest aktualisiert. Der Client des Lesers löst den Slug lokal zu einem Manifest-Shard auf und ruft dann diese Adresse aus dem nginx-Edge-Cache ab. Die Adresse ist ein Content-Hash, kann also nie anderen Inhalt zurückgeben — dreißig Tage lang cachebar ohne Invalidierungsstrategie.
Besucher-Traffic erreicht nie die API oder PostgreSQL. Ihr Schreibpfad ist auf Ihre Redakteure dimensioniert; Ihr Lesepfad wird durch Ihren Cache dimensioniert.
In einem SaaS werden Sie Kunden haben, die herabstufen, aussetzen und zurückkommen. Was das CMS in diesem Moment tut, ist eine Produktentscheidung, die Sie erben.
corpusctl macht jede Funktion zu einem Modul — Medien, Suche, Webhooks, SEO, GraphQL, Import, Analytics — mit zwei Zuständen:
Zustand
Daten
disabled
Bleiben erhalten. Wieder aktivieren und es macht dort weiter, wo es aufgehört hat.
uninstalled
onUninstall löscht sie, mit doppelter Bestätigung.
Ein Tarif-Downgrade setzt Module auf disabled. Es löscht niemals Daten. Das ist im Code durchgesetzt, nicht in einem Support-Artikel versprochen — was wichtig ist, denn der Kunde, der nach drei Monaten zurückkommt, erwartet, dass seine Inhalte da sind, und zu Recht.
Module dürfen sich außerdem nicht gegenseitig importieren. Eine Service-Registry und ein Event-Bus sind die einzigen Kanäle zwischen ihnen, und die CI lässt den Build scheitern, wenn diese Regel gebrochen wird. Die praktische Konsequenz: Das Entfernen einer Funktion kann das System nicht kaputt machen, sodass Funktionssätze pro Mandant eine Konfigurationsfrage sind und kein Fork.
#Eine Checkliste zur Bewertung jedes CMS für mandantenfähiges SaaS
Ist ein Projekt eine Abrechnungseinheit? Was kostet Kunde 100?
Wo wird Isolation durchgesetzt — Anwendung oder Datenbank?
Kann ein Nutzer unterschiedliche Rollen in unterschiedlichen Mandanten haben?
Werden Lesezugriffe abgemessen? Von wem — Ihnen oder den Besuchern Ihrer Kunden?
Was passiert mit den Daten beim Downgrade?
Können Sie einen Mandanten über die API bereitstellen, ohne einen Menschen im Panel?
Gibt es einen Kontingent-Zähler pro Mandant, den Sie auslesen und abrechnen können?
Frage eins eliminiert die meisten Kandidaten, bevor Sie zu Frage zwei kommen.
Ein Headless-CMS, das zu Next.js passt, statt gegen es zu kämpfen
Draft-Modus, ISR, der App Router und die Render-Ebene. Was wirklich zählt, wenn Sie ein Headless-CMS an Next.js anbinden — und die drei Wege, wie es schiefgeht.