Sécurité IA

RAG multi-tenant : patterns d'isolation cross-clients

Servir un RAG à plusieurs clients sur la même infrastructure exige des choix d'architecture stricts. Trois patterns d'isolation, leurs trade-offs réels, et le bon choix selon votre criticité.

Aroua Biri 9 min

Servir un RAG (Retrieval Augmented Generation) à plusieurs clients sur une infrastructure partagée — pattern multi-tenant — est l'architecture la plus courante en 2026 pour les SaaS B2B. Mais c'est aussi celle où une mauvaise architecture mène le plus rapidement à un cross-tenant leak : un client voyant les données d'un autre. Voici les trois patterns d'isolation, leurs trade-offs, et le choix raisonné.

Le risque cross-tenant en RAG

Un système RAG type :

  1. Documents indexés en chunks, embeddings stockés dans une vector DB.
  2. Requête utilisateur → embedding → top-K documents les plus proches.
  3. Top-K injecté dans le prompt LLM → réponse.

Le risque : à l'étape 2, un top-K peut contenir des documents d'autres tenants si l'isolation n'est pas appliquée correctement. Conséquence : le LLM répond avec des données qui ne devraient pas être visibles à ce tenant.

Causes typiques :

  • Filtrage par metadata oublié dans une nouvelle route.
  • Bug de logique dans le filtre.
  • Mauvaise utilisation d'un cache partagé.
  • Migration ratée entre versions.

Voir aussi RAG en production : sécuriser ingestion, embeddings et rétrieval.

Les trois patterns d'isolation

Pattern 1 — Filtrage par metadata (faible coût, faible isolation)

Tous les vecteurs sont dans le même index, distingués par un champ tenant_id. Les requêtes filtrent.

``python results = vector_db.search( query_embedding, filter={"tenant_id": current_tenant_id}, top_k=5 ) ``

Avantages :

  • Coût d'infrastructure le plus bas.
  • Cache partagé optimal.
  • Setup le plus simple.

Inconvénients :

  • Risque résiduel élevé : un bug dans le filtre = leak immédiat.
  • Pas de garantie cryptographique : c'est de la logique applicative.
  • Pas adapté pour des données très sensibles ou réglementées.

Quand l'utiliser :

  • Tenants tous au même niveau de criticité.
  • Stack mature, well-tested.
  • Données peu sensibles (catalogue produits, knowledge base FAQ, etc.).
  • Phase d'apprentissage et de prototype.

Pattern 2 — Index séparés (coût moyen, isolation forte)

Un index distinct par tenant. Les requêtes vont par construction dans le bon index.

``python # Tenant routing au niveau infra, pas dans la requête index_name = f"tenant-{current_tenant_id}-docs" results = vector_db.get_index(index_name).search(query_embedding, top_k=5) ``

Avantages :

  • Isolation par construction : un mauvais routing pourrait leaker, mais le code de routing est centralisé et testé.
  • Performances de recherche meilleures (indices plus petits).
  • Suppression d'un tenant = drop d'un index, instantané.

Inconvénients :

  • Coût d'infrastructure plus élevé (chaque index a son overhead).
  • Pas adapté à un volume très élevé de tenants (10 000+ peut être problématique).
  • Plus de complexité opérationnelle.

Quand l'utiliser :

  • SaaS B2B avec 10-1000 tenants moyens à grands.
  • Données sensibles (CRM, contracts, knowledge base interne).
  • Compliance qui demande isolation forte (HDS, secret bancaire).

C'est mon défaut recommandé pour les SaaS B2B modernes.

Pattern 3 — Infrastructure dédiée (coût élevé, isolation maximale)

Un cluster ou une instance vector DB par tenant. Pas de partage de ressources.

``python # Multi-cluster routing cluster = tenant_to_cluster_map[current_tenant_id] results = cluster.search(query_embedding, top_k=5) ``

Avantages :

  • Isolation la plus forte possible (cryptographique au niveau réseau).
  • Compliance maximale.
  • Performance dédiée par tenant (pas de noisy neighbor).
  • Permet personnalisation forte par tenant (modèles d'embedding différents, par exemple).

Inconvénients :

  • Coût d'infrastructure très élevé (×N tenants).
  • Setup complexe.
  • Pas adapté pour un grand nombre de tenants.

Quand l'utiliser :

  • Tenants critiques avec exigences réglementaires fortes (santé, défense, secret bancaire).
  • Petit nombre de tenants premium (<50).
  • Tenants qui paient pour le niveau d'isolation.

Choix selon le profil de criticité

| Profil | Pattern recommandé | |---|---| | MVP, faible volume, données peu sensibles | Pattern 1 (metadata) | | SaaS B2B standard, données business | Pattern 2 (index séparés) | | SaaS healthtech, fintech, enterprise sensible | Pattern 2 ou 3 selon criticité | | Très grand volume tenants (10k+) | Pattern 1 avec audit renforcé OU sharding | | Acteur très exposé (Tier 1 enterprise) | Pattern 3 |

Vector DBs et leur support multi-tenant

Pinecone (Pinecone Serverless)

  • Support natif des indices par tenant (Pattern 2).
  • Namespaces dans un index pour Pattern 1.
  • Bon pour les trois patterns.

Weaviate

  • Multi-tenancy natif (depuis v1.20) avec tenant ID, recommandé pour Pattern 1 ou 2.
  • Performances optimisées pour Pattern 2.

Qdrant

  • Collection dédiée par tenant (Pattern 2) supporté nativement.
  • Filtres par metadata (Pattern 1) bien supportés.

Milvus / Zilliz Cloud

  • Database par tenant possible.
  • Bon pour Pattern 2.

pgvector (PostgreSQL)

  • Schémas séparés par tenant pour Pattern 2.
  • Filtrage par tenant_id pour Pattern 1.
  • Bon choix si vous êtes déjà sous PostgreSQL.

LanceDB

  • Tables séparées par tenant (Pattern 2) légères.
  • Bon pour les setups simples avec peu d'opérationnel.

Checks de sécurité runtime

Quel que soit le pattern :

1. Tests de cross-tenant isolation systématiques

À chaque release, tests automatiques qui :

  • Connectent en tant que tenant A.
  • Tentent une requête qui ne devrait retourner que les données du tenant A.
  • Vérifient que zéro document du tenant B/C/D apparaît.

```python def test_no_cross_tenant_leak(): # Tenant A asks generic question response_a = rag.query(tenant="A", query="What is in our docs?")

# Verify no tenant B markers in response for marker in TENANT_B_DOCUMENT_MARKERS: assert marker not in response_a.context_documents ```

2. Logs structurés par tenant

Chaque requête loggée avec tenant_id. Si une requête retourne des docs avec un autre tenant_id, alerte critique.

3. Audit régulier

Trimestriel : revue manuelle de log d'échantillon, scan des accès anormaux, vérification des permissions.

L'erreur la plus coûteuse

Migrer du Pattern 1 au Pattern 2 ou 3 après avoir grandi est très coûteux. Refacto de routing, migration de données, downtime, tests. La décision d'architecture en début de projet a 10x plus de poids qu'une décision intermédiaire.

Pour la majorité des SaaS B2B, commencer directement en Pattern 2 est la bonne décision : coût initial maîtrisé, isolation forte par construction, scalabilité acceptable.

Articulation avec la conformité

  • ISO 27001 : isolation multi-tenant est implicite dans Annexe A 8.x.
  • SOC 2 : auditeurs vérifient les contrôles d'isolation.
  • HDS : isolation forte requise (Pattern 2 ou 3).
  • DORA : pour les SaaS financiers, attendez-vous à devoir prouver Pattern 2 ou 3.

Investir dans une isolation forte dès le départ = ROI direct sur les certifications futures.

Un sujet connexe chez vous ?

20 minutes pour cadrer ensemble. Aucune offre commerciale envoyée à froid.

Réserver un échange Calendly