App LLM multi-tenant: isolare i clienti su un modello condiviso
Un modello Bedrock condiviso, molti clienti. Il modello è stateless: l'isolamento tocca a te, delimita il retrieval, la quota e l'identità per tenant.

Quando molti clienti condividono un modello Bedrock, il modello non offre alcun isolamento e non l'ha mai offerto. È una funzione stateless: stesso input, stesso comportamento, nessuna memoria di chi l'ha chiamata. Ogni confine tra i tenant va costruito nei livelli attorno al modello, non atteso da esso. I team sbagliano questo punto, danno per scontato che il servizio gestito gestisca anche la separazione, e mandano in produzione un'app dove i dati, i costi e il carico di un tenant filtrano in quelli di un altro. Il modello condiviso va bene. Il condividere tutto il resto è il problema.
La parte rassicurante è che proprio il fatto che il modello sia stateless è ciò che rende il multi-tenancy gestibile. Non c'è stato per singolo tenant all'interno del modello da far trapelare, perché non c'è stato affatto. L'isolamento si riduce a tre confini concreti che già sai costruire: quali dati può raggiungere la richiesta di un tenant, quanta capacità condivisa può consumare, e sotto quale identità viene eseguita.
Isolamento dei dati: delimita il retrieval, non il modello
Il vero rischio di fuga in un'app RAG o basata su agenti non sono i pesi, è il contesto che metti davanti a loro. Se la domanda del tenant A recupera i documenti del tenant B, hai una violazione dei dati travestita da risposta utile. Quindi il livello di retrieval è dove vive la separazione tra tenant.
Due forme praticabili, a seconda di quanto deve essere rigido il confine:
- Knowledge Base per tenant. Il confine rigido. Ogni tenant ottiene la propria Bedrock Knowledge Base, così una query può recuperare solo dal corpus di quel tenant. Il più pulito da ragionare, con più parti in movimento da gestire man mano che cresce il numero di tenant.
- Store condiviso, filtrato per tenant. Un unico store vettoriale con un filtro obbligatorio per tenant-ID su ogni query, così i risultati sono delimitati dai metadati. Più economico da gestire, ma il filtro ora è sicurezza portante. Deve essere applicato lato server da un'identità autenticata, mai da un valore che il client può impostare.
Il fallimento da evitare è filtrare su un tenant ID arrivato nel corpo della richiesta. Se il client può nominare il proprio tenant, può nominarne uno altrui. Deriva il tenant dal principal autenticato e applica il confine dove il client non può raggiungerlo.
Il vicino rumoroso: una quota condivisa è un guasto condiviso
Bedrock limita il traffico su token al minuto a livello di account e di modello. Quel numero è condiviso tra ogni tenant che colpisce quel modello nel tuo account. Quindi un tenant che fa girare un pesante job batch consuma il budget di token condiviso, e ogni altro tenant inizia a raccogliere errori di throttling per un carico che non ha generato. Il modello è isolato logicamente ma accoppiato operativamente.
Isolamento qui significa misurare e limitare per tenant prima che lo faccia il tetto condiviso al posto tuo:
- Budget di token per tenant. Traccia i token consumati per tenant per finestra temporale e rifiuta o metti in coda un tenant che supera la propria allocazione, così il suo picco non può mangiare il pool condiviso.
- Code eque. Un pool di worker per tenant, delimitato, davanti al modello trasforma il picco di un tenant in un rallentamento di quel tenant, non un'interruzione per tutti.
- Livelli di priorità. Se i tenant pagano per livelli di servizio diversi, imponilo nel controllo di ammissione. Un batch a livello gratuito non dovrebbe poter affamare il traffico interattivo di un tenant pagante.
Identità: il confine del tenant deve arrivare fino ai tool
L'isolamento non può fermarsi al retrieval. Nel momento in cui un agente chiama un tool, legge da un database, o scrive su uno storage, il confine del tenant deve viaggiare con la richiesta. Questo significa che la richiesta viene eseguita sotto un'identità delimitata al tenant, così che anche se il modello viene convinto a richiedere i dati sbagliati, le credenziali dietro il tool non possano recuperarli. Il livello del modello non si fida di nulla; il livello IAM impone tutto. Questo è il principio del minimo privilegio applicato per tenant, ed è ciò che impedisce a un tentativo di prompt injection di trasformarsi in una lettura cross-tenant.
Il punto chiave
Un modello condiviso non è un'app dove tutto è condiviso. Il modello è stateless, quindi non fornisce alcun isolamento e non ne ha bisogno di uno proprio da proteggere. Il tuo compito sono i tre confini attorno a esso: delimita il retrieval così che un tenant veda solo i propri dati, misura e limita la capacità così che nessun tenant affami gli altri sulla quota di token condivisa, e porta un'identità per tenant fino ai tool così che una credenziale delimitata sia l'ultima linea di difesa quando il livello del prompt viene ingannato. Costruisci questi tre e un modello serve molti clienti in sicurezza. Salta anche solo uno e il modello servirà volentieri i dati del cliente sbagliato al cliente sbagliato.
Da leggere ora
- IAM for LLM Apps: Least Privilege When the Caller Is a Model, sull'identità delimitata che porta il confine del tenant fino ai tool.
- Cutting Amazon Bedrock Knowledge Base Costs by ~90% with pgvector, sullo store vettoriale filtrato per tenant che rende conveniente il retrieval condiviso.
Per il lato piattaforma e isolamento multi-account dello stesso problema, le note di campo sul cloud sono su ercan.cloud, e l'hub è su ercanermis.com.
Altro da Ercan
Altri due siti, stesso autore, terreno diverso.
Cloud, AWS, EKS, Terraform, platform engineering.
Note sul campo da sistemi in produzione. EKS, IAM, Terraform su scala organizzativa, observability, ottimizzazione dei costi.
Visita ercan.cloud →L'hub. Chi sono, consulenza, contatti.
Hub personale per entrambe le tracce di scrittura. Chi sono, come funziona la consulenza, come contattarmi.
Visita ercanermis.com →