<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Armin Burger</title>
    <description>The latest articles on DEV Community by Armin Burger (@armin_burger_ab136b2f8bb1).</description>
    <link>https://dev.to/armin_burger_ab136b2f8bb1</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2642895%2F737f3d5a-6e7a-4a79-a423-4f3944b3bbbc.png</url>
      <title>DEV Community: Armin Burger</title>
      <link>https://dev.to/armin_burger_ab136b2f8bb1</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/armin_burger_ab136b2f8bb1"/>
    <language>en</language>
    <item>
      <title>Beyond `tenant_id`: Why Classical Multi-Tenancy Fails for RAG Systems</title>
      <dc:creator>Armin Burger</dc:creator>
      <pubDate>Fri, 18 Sep 2026 12:09:46 +0000</pubDate>
      <link>https://dev.to/armin_burger_ab136b2f8bb1/beyond-tenantid-why-classical-multi-tenancy-fails-for-rag-systems-1off</link>
      <guid>https://dev.to/armin_burger_ab136b2f8bb1/beyond-tenantid-why-classical-multi-tenancy-fails-for-rag-systems-1off</guid>
      <description>&lt;p&gt;ost engineering teams assume that because they have implemented row-level security (RLS) and a &lt;code&gt;tenant_id&lt;/code&gt; column in their relational database, their application is securely multi-tenant. This assumption holds true for traditional CRUD applications. However, when you integrate Large Language Models (LLMs) and Retrieval-Augmented Generation (RAG) pipelines, classical isolation patterns become dangerously insufficient.&lt;/p&gt;

&lt;p&gt;The core issue is that AI systems introduce new attack surfaces and failure modes that do not exist in standard SaaS architectures. Here are four critical frontiers where traditional multi-tenancy breaks down, along with the architectural adjustments required to secure them.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Vector Store Isolation: The Silent Leak Risk
&lt;/h2&gt;

&lt;p&gt;Approximate Nearest Neighbor (ANN) indexes, which power most vector databases, lack default access controls comparable to SQL. If you rely solely on post-filtering results by &lt;code&gt;tenant_id&lt;/code&gt;, you risk exposing data during the search phase or leaking metadata through similarity scores.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; You must enforce isolation at the index level. Use namespace models or explicit pre-filtering strategies within the vector store itself. Treating the tenant boundary as an absolute filter component—rather than just a metadata tag—is essential to prevent cross-tenant data leaks.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Semantic Caching: Keys Must Include Tenant ID
&lt;/h2&gt;

&lt;p&gt;Caching is often the most overlooked frontier for security breaches in AI apps. Semantic caches retrieve answers based on question similarity rather than exact matches. If your cache key does not include the &lt;code&gt;tenant_id&lt;/code&gt; as a hard component, a query from Tenant A might match a cached response generated for Tenant B.&lt;/p&gt;

&lt;p&gt;This leads to silent failures: users receive plausible-sounding but incorrect answers derived from another company’s data. There are no error codes or crashes; the system simply returns wrong information.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Ensure the tenant ID is a mandatory part of every semantic cache key. Maintain per-tenant cache spaces instead of using a single global cache where tenant identity is treated merely as a similarity signal.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Token Cost Management: Beyond Request Rate Limiting
&lt;/h2&gt;

&lt;p&gt;Traditional rate limiting counts requests per minute. In RAG products, this is inadequate because token costs vary significantly by provider, model, and direction (input vs. output). A "noisy neighbor" can consume disproportionate resources with a few complex prompts, impacting latency and cost for all other tenants.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Shift from request counting to token usage tracking. Implement reservation patterns to manage resource allocation effectively, ensuring that one tenant’s heavy usage does not degrade service quality for others.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Context Assembly and Guardrails
&lt;/h2&gt;

&lt;p&gt;Hardcoding global middleware for guardrails fails when different tenants have varying compliance needs and latency tolerances. Furthermore, concurrency issues in prompt assembly can lead to catastrophic mixing of sensitive data if module-global state is used.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Dynamic Guardrails:&lt;/strong&gt; Configure PII filters and prompt-injection defenses per tenant.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Strict Scoping:&lt;/strong&gt; Avoid object sharing between parallel requests. Place base system instructions before the cache boundary, and keep all tenant-specific context (names, configs, RAG data) strictly after it.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Granular Observability:&lt;/strong&gt; Global average metrics mask individual tenant failures. Measure evaluation metrics like RAGAS faithfulness at the tenant granularity to detect subtle quality degradation early.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Security architecture for AI requires moving beyond database-level isolation. It must encompass vector indices, prompt construction logic, and API-level caching mechanisms. Thinking through each dimension individually during design beats bundling them under a generic "multi-tenancy" label, because failure modes in AI systems are silent and subtle, not obvious crashes.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>rag</category>
      <category>security</category>
    </item>
    <item>
      <title>Stop Hardcoding Your AI Guardrails: A Multi-Tenant Configuration Strategy</title>
      <dc:creator>Armin Burger</dc:creator>
      <pubDate>Tue, 15 Sep 2026 15:36:15 +0000</pubDate>
      <link>https://dev.to/armin_burger_ab136b2f8bb1/stop-hardcoding-your-ai-guardrails-a-multi-tenant-configuration-strategy-5bha</link>
      <guid>https://dev.to/armin_burger_ab136b2f8bb1/stop-hardcoding-your-ai-guardrails-a-multi-tenant-configuration-strategy-5bha</guid>
      <description>&lt;p&gt;Most early-stage AI products make a critical architectural mistake: they implement security guardrails as global, hardcoded middleware. While this works for a single use case, it becomes a liability the moment you onboard a second enterprise customer with different regulatory needs.&lt;/p&gt;

&lt;p&gt;The core problem is that "one-size-fits-all" security fails in multi-tenant environments. A healthcare tenant requires strict PII detection and high latency tolerance, while a developer tools tenant prioritizes low-latency responses and minimal false positives. When these conflicting requirements meet a static codebase, you face risky rewrites instead of simple config changes.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Pipeline Model
&lt;/h2&gt;

&lt;p&gt;Instead of treating guardrails as binary on/off feature flags, model them as an ordered, parameterized pipeline. This allows each tenant to define their own sequence of checks for both input and output streams.&lt;/p&gt;

&lt;p&gt;A robust configuration structure looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"input"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"pii_detection"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"sensitivity"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"high"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"redact"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"toxicity_check"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"sensitivity"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"medium"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"flag"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"output"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"harmful_content"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"sensitivity"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"low"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"block"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By loading this JSON from a database per tenant, you enable adjustments without code deployments. Actions like &lt;code&gt;block&lt;/code&gt;, &lt;code&gt;flag&lt;/code&gt;, or &lt;code&gt;redact&lt;/code&gt; provide granular control over how violations are handled.&lt;/p&gt;

&lt;h2&gt;
  
  
  Handling Streaming Output
&lt;/h2&gt;

&lt;p&gt;Input guardrails are relatively straightforward because you can analyze the full prompt before processing. Output guardrails present a unique architectural conflict: real-time streaming UX versus holistic text analysis.&lt;/p&gt;

&lt;p&gt;Waiting for the entire response to finish defeats the purpose of streaming, but checking every token individually misses context-dependent toxicity. The solution is a middle-ground approach: process output in sentences or chunks. If a chunk triggers a rule, abort the stream immediately. This balances user experience with security compliance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Audit Trails and Compliance
&lt;/h2&gt;

&lt;p&gt;Guardrails are not just blockers; they are evidence generators. Without granular audit logs containing confidence scores and specific triggered rules, you cannot prove compliance to auditors—you can only claim it exists.&lt;/p&gt;

&lt;p&gt;Implementing tenant-specific "golden sets" for regression testing ensures that configuration changes do not inadvertently break security policies. Furthermore, sensitivity thresholds should be treated as business risk decisions configurable by the tenant, not fixed by the platform.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Two-Tier Configuration Model
&lt;/h2&gt;

&lt;p&gt;To balance usability with legal safety, adopt a two-tier model:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Coarse Presets:&lt;/strong&gt; Allow self-service tenants to choose from predefined security profiles (e.g., "Standard," "Strict").&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Granular Overrides:&lt;/strong&gt; Enable Enterprise customers to tweak specific parameters via approval workflows.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Hardcoding guardrails globally is not just bad practice; it is a guaranteed path to losing enterprise contracts. By shifting to a configurable, per-tenant pipeline, you transform security from a rigid constraint into a flexible product feature.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>architecture</category>
      <category>security</category>
      <category>systemdesign</category>
    </item>
  </channel>
</rss>
