Hybrid-Persistenz pro Kunden-Tenant
Kontext
Beim Design des Produkt-Bundles (produkt-bundle) entstand die Idee, das eigene Markdown-Vault-Pattern aus agent-native-architektur auch fuer Kunden-Tenants zu uebernehmen — Daten-Souveraenitaet, DSGVO-Export trivial, Tool-agnostisch via Obsidian, transparenter Audit-Trail.
Bei genauerem Nachfassen kam die berechtigte Gegenfrage auf: was passiert bei create_order(amount, customer) in einem Restaurant-Use-Case? Bei create_reservation(date, table) mit zehn parallelen Buchungen? Bei record_payment(invoice_id, amount) mit Konsistenz-Anforderung gegen Bestands-Decrement?
Reines Markdown bricht hier strukturell:
- Keine ACID-Transaktionen. “Order anlegen + Bestand decrementieren + Bestaetigung schicken” ueber drei Files: wenn Schritt 2 bricht, ist Schritt 1 schon committed ohne Rollback-Mechanik.
- Race Conditions bei Concurrency. Zwei parallele Tool-Calls die in dasselbe File schreiben — File-Locking auf S3 ist komplex und nicht durchsetzbar.
- Keine Constraints. Wenn der Agent
amount: -500schreibt, frisst Markdown das ohne zu mucksen. DB hatCHECK (amount > 0). - Aggregations-Performance. “Alle offenen Bestellungen ueber 1000 €” ueber 5000 Files lesen ist langsam. Frontmatter-Index waere noetig — der wieder konsistent gehalten werden muss.
- Schema-Drift. Zwei Files koennen inkompatibel sein wenn das Schema sich aendert. DB hat Migrations als bewaehrte Disziplin.
Gleichzeitig hat Markdown klare Vorteile fuer eine andere Datenklasse:
- Read-heavy, semi-strukturierte Inhalte (Notizen, Recherchen, Meetings, Cross-Refs) brauchen keinen DB-Apparat.
- Datenuebertragbarkeit (DSGVO Art. 20) ist mit Markdown trivial —
aws s3 syncexportiert das ganze Wissen, lesbar in jedem Editor. - Transparenz als Verkaufs-Argument gegen Black-Box-SaaS.
- Agent-native — der Agent kann mit
read/write/greparbeiten wie ein Mensch in einem Texteditor.
Das eigene Vault von Marvin (siehe agent-native-architektur) macht das richtig: keine Buchungen, keine Zahlungen, keine Bestaende liegen darin. Die liegen in Papierkram, in den Bank-Konten, in TicketPAY. Im Vault liegen Notizen, Meetings, Recherchen, Cross-Refs. Genau diese Trennung muss das Customer-facing Modell uebernehmen.
Optionen
Option A — Reines Markdown-Vault pro Tenant
Pro: Einheitliches Modell, maximale Daten-Souveraenitaet, Daten-Export trivial, Branding “alles als Files”.
Contra: Bricht bei transaktionalen Tools strukturell. Workarounds (File-Locking, Frontmatter-Index, externes Lock-Service) duplizieren halbgar was Datenbanken seit Jahrzehnten machen.
Option B — Reine DynamoDB pro Tenant (kein Vault)
Pro: Solide bei Konsistenz und Performance. Eine Persistenz-Schicht.
Contra: DSGVO-Export ist DB-Dump (technisch, weniger fuer Kunden lesbar), Vendor-Lock-In-Aenstellung gegenueber AWS, weniger Transparenz, agent-native nur durch Custom-Tools-Layer. Faellt zurueck auf “klassisches SaaS mit AI-Layer”, verliert das Differenzator-Argument.
Option C — Hybrid: Markdown-Vault fuer Knowledge, DynamoDB fuer Operational
Pro Datenklasse die richtige Schicht. Beide KMS-encrypted pro Tenant, gleiche ABAC-Tag-Topology. Gemeinsamer Customer-Managed-Key bedeutet einheitliche Tenant-Isolation auf Storage-Layer, nicht nur Application-Layer.
Pro: Spielt die Staerken beider Patterns aus, niemand wird unfair eingesetzt. Knowledge bleibt als Markdown exportierbar und lesbar, Operational bleibt konsistent und performant. DSGVO-Argumentation klar trennbar pro Datenklasse.
Contra: Zwei Persistenz-Schichten zu pflegen, klare Konvention noetig welche Daten wohin gehoeren. Risiko des Schleichens (Operational landet im Vault weil “Markdown ist cool”) wenn nicht diszipliniert dokumentiert.
Option D — Externes System bleibt Source-of-Truth, wir cachen nur
Bei den meisten Operational-Daten (Lexoffice-Rechnungen, TicketPAY-Events, Papierkram-Buchungen) ist das Source-System schon transaktionsfaehig — wir muessen nicht selbst eine DB betreiben, sondern proxien per API. Nur wo der Kunde wirklich eigene Operational-Daten haelt (Reservierungen ueber unsere UI, Workflow-State, Usage-Counter) brauchen wir DB.
Pro: Reduziert eigene DB-Verantwortung dramatisch. Der Kunde “besitzt” Operational-Daten weiterhin im Source-System.
Contra: Faellt auf Hybrid zurueck — wir brauchen DB fuer das was nirgendwo sonst hingeht. Aber Mengengeruest ist klein.
Entscheidung
Option C kombiniert mit Option D als Optimierung.
Pro Kunden-Tenant zwei Persistenz-Schichten:
-
S3-Markdown-Vault (
vault-tenant-<id>, KMS-encrypted) fuer Knowledge-Daten: Notizen, Meetings, Recherchen, Kunden-Akten (deren Endkunden), Cross-Refs, Skills/Workflows als Files, Konfiguration, Verträge, Agent-Run-Logs. Schema folgt dem agent-native-Pattern aus agent-native-architektur. -
DynamoDB-Tabelle (
vault-indexmittenant_id-Partition oder pro Tenant eigene Tabelle, je nach Tier, KMS-encrypted) fuer Operational-Daten:- API-Tokens (verschluesselt)
- Workflow-State (z.B. “Beleg in Approval Schritt 3 von 5”)
- Custom Operational Daten die in keinem Source-System landen (z.B. Reservierungen ueber unsere UI bevor in OpenTable synced)
- Usage-Counter fuer Stripe-Metered-Billing
- Audit-Log mit Retention-Policy
- Frontmatter-Index ueber das Markdown-Vault (fuer schnelle Queries)
Source-of-Truth-Default fuer Operational-Daten: das jeweilige externe Source-System (Lexoffice, Papierkram, TicketPAY, M365). Wir proxien per API, persistieren bei uns nur den Workflow-State und ggf. einen Knowledge-Snapshot ins Markdown-Vault. Das reduziert die eigene Operational-DB auf ein Minimum.
Tool-Design-Konvention: Jedes MCP-Tool bekommt im Frontmatter dokumentiert wo seine Schreibe landet — writes_to: source_system oder writes_to: db oder writes_to: vault oder Mehrfach-Werte. Das ist ein Design-Review-Anker — wenn jemand create_order ins Vault schreibt, faengt die Konvention das ab.
Konsequenzen
Architektur:
Pro Tenant in av-production (Phase 2 der Pipeline):
├── S3 vault-tenant-<id>/ Knowledge (Markdown)
│ ├── CLAUDE.md tenant-spezifische Behavior
│ ├── _meta/ Schema, Konventionen, Skills
│ ├── kunden/ Endkunden des Tenants
│ ├── projekte/, meetings/, runs/ wie agent-native-Pattern
│ ├── ticketpay/, lexoffice/, m365/ Knowledge-Snapshots aus MCP-Calls
│ └── inbox/ noch nicht einsortiert
└── DynamoDB-Eintraege mit tenant_id Operational
├── tokens API-Keys verschluesselt
├── workflow_state orchestrierter State
├── custom_operational Reservierungen, Tickets, etc.
├── usage_counter Stripe-Metered
├── audit_log Compliance
└── vault_index Frontmatter-Lookup
KMS-Customer-Managed-Key pro Tenant, ABAC-Tag aws:PrincipalTag/TenantId durchgesetzt sowohl auf S3 wie auf DynamoDB. Tenant-Isolation auf Storage-Layer, nicht Application-Layer.
Bauzeitliche Konsequenz:
Phase 2 der MCP-Pipeline (_index) wird groesser — sie baut beide Persistenz-Schichten parallel auf. Geschaetzter Mehraufwand vs reine Token-Storage: +1 Woche, da sich die ABAC-Topology zwischen S3 und DynamoDB teilen laesst.
DSGVO-Story:
| Recht | Erfuellung |
|---|---|
| Auskunft (Art. 15) | S3-Listing der Vault-Files + DynamoDB-Query nach tenant_id, beides Tenant-isoliert, Auswertung trivial |
| Datenuebertragbarkeit (Art. 20) | aws s3 sync exportiert Markdown-Vault, DynamoDB-Items als JSON-Dump |
| Berichtigung (Art. 16) | Markdown editieren oder DynamoDB-Update, beides API-faehig |
| Loeschung (Art. 17) | KMS-Key disabled = alle Daten dieses Tenants kryptographisch gloeschelt; Hard-Delete der Files+Items als Followup |
| Audit | DynamoDB audit_log plus S3-Versioning auf dem Vault |
Die Argumentation ist staerker als bei klassischen DB-only-SaaS, weil der Knowledge-Layer ein Self-Contained Markdown-Repo ist, das der Kunde direkt verstehen kann (nicht nur lesen — verstehen, weil Files lesbar sind).
Anti-Patterns die wir explizit ablehnen:
- Operational-Daten ins Markdown ablegen (z.B.
bestellungen/2026-05-10-order-42.mdals primaerer Datensatz). Knowledge-Snapshot zusaetzlich zur DB ist okay, aber nicht als Source-of-Truth. - Knowledge in DynamoDB ablegen (z.B. Meeting-Protokolle als Items). Markdown ist hier sauberer und exportierbar.
- Custom-Lock-Service auf S3 bauen um Markdown-Concurrency zu loesen. Wenn Locks noetig sind, ist es Operational-Daten und gehoert in DB.
- Frontmatter-Index in S3 selbst halten (z.B. ein zentrales
_index.json). Wenn Index gebraucht wird, gehoert er in DynamoDB.
Tier-Sichtbarkeit (siehe produkt-bundle):
| Tier | Vault-Sichtbarkeit | DB-Sichtbarkeit |
|---|---|---|
| Solo | Web-Dashboard mit Markdown-Preview, Suche, Edit | nur via Tool-Calls (transparent) |
| Team | Plus S3-Read-Access fuer Export | Plus Audit-Log-Export |
| Custom | Plus WebDAV-Mount oder Git-Mirror, eigenes Schema | Plus eigene DynamoDB-Tabelle, eigenes Backup |
Related
- agent-native-architektur — konzeptueller Vorlauf, das Markdown-Vault-Pattern fuer das eigene Vault
- aws-multi-account-strategie — Account-Topologie (
av-productionfuer shared Tenants,av-<kunde>fuer Custom-Tier) - produkt-bundle — Produkt-Strategie die diese Architektur nutzt
- ecs-express-statt-app-runner — Compute-Layer
- AWS Security Blog: SaaS Tenant Data with ABAC and Client-Side Encryption — Pattern fuer DynamoDB-Tenant-Isolation