Das häufigste Muster, das wir bei RAG-Projekten im DACH-Mittelstand sehen: DSGVO wird als organisatorische Aufgabe behandelt, nicht als technische. Der Datenschutzbeauftragte wird informiert, die AGB werden ergänzt, ein DPA mit dem LLM-Provider wird unterzeichnet — und alle sind zufrieden. Bis Sprint 12, wenn das System produktiv gehen soll und die technische Umsetzung DSGVO-relevanter Anforderungen fehlt.
Dieser Beitrag beschreibt eine Architektur, die die vier häufigsten technischen Anforderungen aus DSGVO und EU AI Act von Anfang an in die Pipeline einbaut: EU-Region-Deployment, PII-Filtering, Data-Lineage, Right-to-Erasure.
Was DSGVO für eine RAG-Pipeline konkret bedeutet
Vier Anforderungen aus der Praxis:
Datenlokalität. Alle personenbezogenen Daten müssen entweder in der EU verarbeitet werden oder es muss eine passende Rechtsgrundlage für den Transfer geben (Standardvertragsklauseln nach Art. 46 DSGVO, Angemessenheitsbeschluss der EU-Kommission). Nach Schrems II ist der Transfer in die USA nicht mehr per Angemessenheitsbeschluss abgedeckt.
Rechenschaftspflicht. Ihr müsst dokumentieren können, welche personenbezogenen Daten in welcher Form verarbeitet wurden, für welchen Zweck, mit welcher Rechtsgrundlage. Bei RAG heißt das: welche Chunks im Vector-Store enthalten PII, welche Prompts wurden vom Modell verarbeitet, welche Antworten wurden geliefert.
Recht auf Löschung. Betroffene können nach Art. 17 DSGVO die Löschung ihrer Daten verlangen. Bei RAG bedeutet das: euer Vector-Store muss löschbare Einheiten haben — meist Chunk-Level oder Dokument-Level.
Recht auf Auskunft. Auf Anfrage müsst ihr sagen können, welche Daten zu einer Person gespeichert sind. Bei RAG heißt das: der Index muss durchsuchbar sein nach personenbezogenen Attributen.
Die Architektur
Wir strukturieren die Pipeline in fünf Layer, jeder mit spezifischen DSGVO-Verantwortungen.
Layer 1: Ingestion und PII-Klassifizierung
Beim Import von Quelldokumenten wird jeder Chunk mit einem PII-Score annotiert. Ein einfacher Regex-basierter Scanner erkennt E-Mail-Adressen, Telefonnummern, IBANs, deutsche Adressen. Für komplexere Fälle (Namen, Kontexte) kann ein NER-Modell wie spaCy oder ein LLM-basierter Klassifikator eingesetzt werden.
Ergebnis: jeder Chunk hat ein PII-Level-Metadatum (none, low, high) und optional eine Liste erkannter PII-Typen. Chunks mit pii=high werden entweder ausgeschlossen oder in eine separate Collection mit strengeren Zugriffsrechten geleitet.
Für die Ingestion-Pipeline heißt das konkret:
class ChunkMetadata(BaseModel):
source_id: str # Herkunfts-Dokument
source_version: str # Dokument-Version zum Ingestion-Zeitpunkt
ingested_at: datetime # Zeitstempel
tenant_id: str # Multi-Tenant-Isolation
pii_level: Literal["none", "low", "high"]
pii_types: list[str] # z.B. ["email", "phone"]
Diese Metadaten sind später Grundlage für Filter, Lineage und Löschung.
Layer 2: Vector-Store mit EU-Region
Die Vector-DB muss in der EU laufen. Für die meisten unserer Setups: pgvector auf PostgreSQL in Frankfurt oder Qdrant Cloud in eu-central. Der Vector-Store bekommt einen expliziten Region-Constraint in der Deployment-Config.
Wichtig: auch das Embedding-Modell muss die Region-Anforderung erfüllen. Wenn ihr für die Embeddings eine externe API (OpenAI, Cohere) nutzt, prüft die aktuelle Region-Konfiguration. Für hoch-sensible Daten setzen wir zunehmend selbst gehostete Embedding-Modelle ein (bge-m3 in einer eigenen GPU-Umgebung oder self-hosted API mit vLLM).
Layer 3: Query-Layer mit PII-Filtering und Prompt-Sanitization
Beim Retrieval sind zwei DSGVO-Themen relevant.
Erstens: Die Nutzer-Anfrage kann selbst PII enthalten ("gibt es Informationen zu Herrn Müller?"). Diese Anfrage darf nicht ungefiltert an einen externen LLM-Provider gehen. Ein Middleware-Layer scannt die Anfrage, ersetzt PII durch Platzhalter, und protokolliert die Ersetzung.
Zweitens: Die zurückgegebenen Chunks müssen die Berechtigung des anfragenden Nutzers respektieren. Ein Filter auf pii_level, tenant_id und ggf. access_group vor der Similarity-Search sorgt dafür.
Konkret als Middleware-Pattern:
async def retrieve(query: str, user: User) -> list[Chunk]:
# 1. Prompt-Sanitization
sanitized_query, replacements = pii_scanner.sanitize(query)
log_pii_replacements(user.id, replacements)
# 2. Filter aufbauen
filters = {
"tenant_id": user.tenant_id,
"pii_level": user.max_pii_level, # z.B. "low" für Standard-Nutzer
"access_group": {"$in": user.groups},
}
# 3. Retrieval mit Filter
chunks = await vector_store.search(
query=sanitized_query,
filters=filters,
top_k=10,
)
return chunks
Layer 4: Generation mit Groundedness-Check
Der LLM-Provider muss vertraglich abgesichert sein. Standard-Vertragsklauseln der EU-Kommission oder ein DPA mit einem EU-basierten Anbieter (Aleph Alpha, Mistral in AWS Frankfurt, self-hosted Llama in eu-west).
Nach der Generation prüft ein zweiter Filter-Layer:
- Enthält die Antwort PII, die nicht in den Retrievergebnissen war? Dann Halluzination — verweigern oder markieren.
- Enthält die Antwort PII aus den Retrievergebnissen? Dann Berechtigungscheck. Wenn der Nutzer die Berechtigung für dieses PII-Level hat: durchlassen. Sonst: PII-Redaction.
Layer 5: Audit und Lineage
Für jede Anfrage wird ein Audit-Log geschrieben:
- Timestamp
- User-ID (gehasht)
- Sanitized Query (nicht die Original-Query mit PII)
- Retrieved Chunk-IDs
- Response (mit oder ohne PII, je nach Berechtigung)
- Latenz-Metriken
Dieser Log ermöglicht sowohl Auskunfts-Anfragen als auch Löschungs-Anfragen. Für die Löschung: der Chunk-Level-Index wird nach source_id durchsucht und alle Chunks eines Betroffenen werden aus dem Vector-Store entfernt. Der Audit-Log-Eintrag zur ursprünglichen Anfrage bleibt bestehen (Ratio: berechtigtes Interesse an Nachvollziehbarkeit), aber ohne personenbezogene Details.
Was auf keinen Fall funktioniert
Zwei Ansätze, die wir öfter sehen und die nicht tragfähig sind.
"Wir anonymisieren beim Ingestion und speichern nur anonymisierte Daten." Klingt gut, ist aber technisch schwer. Anonymisierung ist ein hoher Anspruch (kein Rückschluss auf die Person möglich, auch nicht mit Zusatzwissen). Pseudonymisierung ist realistischer, macht aber die Löschungspflicht nicht weg — der Pseudonymisierungs-Schlüssel darf nicht neben den pseudonymisierten Daten liegen.
"Wir nutzen nur öffentliche Daten." Auch bei öffentlich zugänglichen Websites gelten DSGVO-Regeln, wenn personenbezogene Daten enthalten sind. Der Umstand, dass jemand seinen Namen auf LinkedIn stehen hat, macht die Verarbeitung nicht automatisch DSGVO-konform.
Wann externe Beratung Sinn macht
Wenn ihr diese Architektur in eurem RAG-Projekt umsetzt, ohne dass ein Team dabei ist, das das schon einmal produktiv gebaut hat: der Bau des ersten funktionierenden Setups dauert typischerweise vier bis acht Wochen. Wenn ihr das parallel zu eurem Fach-Fokus machen wollt, ist es sinnvoll, sich Praxiserfahrung dazuzuholen.
Bei NeuralMedic bieten wir für genau diesen Übergang eintägige Architektur-Audits für 2.500 EUR fix an — 1-Pager mit drei priorisierten Empfehlungen und Aufwand-Schätzung. Wenn der Sprint dann kommt, weiß euer Team was zu tun ist. Falls ihr den Sprint mitmachen wollt: unser Rescue-Sprint startet bei 15.000 EUR fix für vier Wochen.
Bevor ihr uns anruft, macht den Reifegrad-Check. Fragen 4 und 5 mappen direkt auf die hier beschriebenen Themen und geben euch einen Sofort-Eindruck, wo ihr steht.