{"slug": "multi-tenant-ai-agents-why-data-isolation-starts-at-the-database", "title": "Multi-Tenant AI Agents: Why Data Isolation Starts at the Database", "summary": "Cockroach Labs warns that multi-tenant AI agent security requires database-level data isolation, not just application-layer filtering, citing 2025 incidents including Salesforce Agentforce's ForcedLeak (CVSS 9.4), ServiceNow Now Assist, and the Salesloft/Drift breach affecting over 700 organizations. The company argues that agentic systems amplify the blast radius of tenant boundary failures because agents can act on leaked data across tool calls at machine speed.", "body_md": "Most SaaS teams shipping agentic features focus on prompt safety and API-layer filtering. But effective AI agent security also depends on controlling what data an agent can access when those application-layer defenses fail.\n\nYour company is building agents that read, reason, and act on behalf of customers. Somewhere in the architecture review, someone asks: \"What happens if the agent touches data it shouldn't?\"\n\nIf the answer depends on the application code doing the right thing every time, that's not an architecture. That's a hope. Multi-tenant agent isolation needs an enforcement boundary that holds regardless of what the application or agent does. It starts at the database.\n\n## Why tenant isolation is different for AI agents\n\nIn a multi-tenant AI agent platform, a tenant boundary failure doesn't stop at returning the wrong data. It enters the agent's reasoning chain, where the agent can act on it: writing to downstream systems, calling APIs, and cascading across dozens of tool calls before any human notices. The blast radius is bounded only by what the agent's tools can access.\n\nIn traditional SaaS, by contrast, a tenant boundary failure returns wrong data to the wrong requester. The error is bounded and usually detectable: one request, one response, visible in logs within seconds.\n\nA misconfigured query is a bug. A misconfigured agent acting on data it shouldn't see can become a breach amplified across tool calls at machine speed. That expanded blast radius is one of the defining [ AI agent security](https://www.cockroachlabs.com/blog/cockroachdb-ai-agents-agent-ready-database/) risks multi-tenant systems have to contain.\n\nThe industry has real examples now. Worth knowing before your team becomes one.\n\n**Salesforce Agentforce, ForcedLeak (CVSS 9.4 per Noma Security's disclosure, 2025): **Attackers embedded malicious instructions in Web-to-Lead form submissions. When Agentforce processed those forms, it couldn't distinguish the instructions from legitimate data and leaked sensitive CRM records to attacker-controlled endpoints.\n\n**ServiceNow Now Assist (2025):** A low-privilege agent parsed crafted prompts in content it was allowed to access, then recruited a more privileged agent to copy and exfiltrate sensitive data, even with built-in prompt injection protections enabled. The actions happened entirely out of view of the affected organization.\n\n**The Salesloft/Drift incident (2025):** More than 700 organizations were ultimately affected, including Cloudflare, Palo Alto Networks, Zscaler, and CyberArk. Attackers moved from Salesloft's GitHub repositories into the Drift AWS environment, then used AI-enabled system integrations to cascade across connected organizations. The blast radius wasn't the original compromise. It was everything those systems could reach from there.\n\nThese three incidents span prompt injection, privilege escalation, and supply chain compromise. Database isolation alone would not have prevented them. What connects them is blast radius: the damage was determined by what the compromised agent or integration could reach. Database isolation is one layer for constraining that reach; the “Limits” section covers what it cannot protect.\n\nTraditional application security assumes a clear boundary between code and data. AI agents dissolve that boundary. When a language model receives instructions from user input, web pages, database records, and tool outputs all at once (each treated as equivalent context), every external data source becomes a potential attack vector.\n\n## What are the three approaches to multi-tenant data isolation?\n\n[ Multi-tenant SaaS architectures](https://www.cockroachlabs.com/blog/6-takeaways-multitenancy-saas-webinar/) generally isolate tenant data through shared schemas with row-level security, separate schemas, or separate databases. For most teams, a shared schema offers the simplest path to scale, but only when tenant boundaries are enforced at the database layer.\n\nWithout database layer enforcement, shared schemas make cross-tenant data leakage easy, and that risk grows as independently configured agents, tools, prompts, and data sources multiply across tenants. Making data isolation an architectural property early helps teams scale tenant count, onboard larger customers, and avoid rebuilding the data layer when security and compliance requirements become stricter.\n\n## Why app-layer filtering isn't enough for tenant isolation\n\nApp-layer filtering isn’t a reliable tenant-isolation boundary, because every code path must correctly implement the same check. The most common approach adds a `WHERE tenant_id = :current_tenant`\n\nclause to every query through the ORM or middleware layer. This works, until it doesn't.\n\nThe failure modes are predictable:\n\nA developer adds a new query path and forgets the filter\n\nAn ORM upgrade changes how parameters are bound\n\nAn agent constructs a SQL query dynamically and the filter gets dropped from the generated string\n\nA prompt injection attack tricks the agent into calling a tool with attacker-controlled parameters\n\n[ IBM's 2025 Cost of Data Breach Report](https://www.ibm.com/think/x-force/2025-cost-of-a-data-breach-navigating-ai) found that, among organizations that experienced AI-related security incidents, 97% lacked proper AI access controls.\n\nIn an agentic system that generates database queries and tool calls at runtime, a single gap can expose data outside the intended retrieval scope; the agent can then act on whatever it retrieves.\n\nDatabase-level isolation removes the advisory quality. The policy runs inside the database engine on every query, regardless of what the application layer does. Prompt injection cannot override the tenant boundary enforced by the policy, a developer can't accidentally omit it, and an ORM change can’t silently strip it.\n\n## How row-level security enforces tenant isolation\n\n[ Row-level security](https://www.cockroachlabs.com/blog/fine-grained-access-control-row-level-security/) (RLS) attaches access policies directly to database tables, making tenant access control an enforced property of the data layer rather than a convention every application path must reproduce. With RLS in\n\n[, tenant data can live in shared tables while access is controlled at the row level based on tenant identity. The database evaluates the policy automatically on every query before returning rows, so the application doesn't have to remember to apply the tenant filter.](https://www.cockroachlabs.com/product/overview/)\n\n__CockroachDB__Without RLS, if Tenant A's agent calls `get_agent_memories()`\n\nand the connection carries the wrong context, the query returns Tenant B's records with no error. The agent reasons on them, acts on them, and may write back to them. Nothing in the call stack signals a problem. Here's what the full implementation looks like for a multi-tenant agent memory table. (Every code block in this article, including the multi-region section, was executed against a live CockroachDB v25.2.2 cluster before publication.)\n\n### Step 1: Create the schema\n\n*Note: this schema uses CockroachDB-specific syntax, including inline INDEX definitions inside CREATE TABLE. It will not run on standard PostgreSQL without modification.*\n\n### Step 2: Enable RLS and create the isolation policy\n\nThe` 'true' `\n\nparameter in `current_setting('app.tenant_id', true)`\n\ntells CockroachDB to return `NULL`\n\nrather than raise an error if the setting isn't present. This gives you a clean fallback rather than a hard crash if something in the connection setup is misconfigured. Handle that `NULL`\n\ncase explicitly in your own policy for safety.\n\n### Step 3: Build the tenant context pipeline\n\nThe one piece that must work correctly for RLS to hold: your application must set the tenant context on every database connection before any queries run. This is the join between your auth layer and the database policy layer.\n\n### Step 4: Agent tool implementation\n\nHere's how this looks from the agent tool layer: the layer that actually generates and executes queries during reasoning.\n\nThe application can still include tenant filters for defense in depth and query performance, but security doesn’t depend on them. RLS remains the enforcement boundary.\n\nRLS also makes operations simpler. Schema changes like adding a column or modifying an index only need to be applied once across all tenants. No duplicated migrations, no tenant-specific deployment logic.\n\n## How geo-partitioning supports data residency requirements\n\nCockroachDB's REGIONAL BY ROW tables let multi-tenant applications [ pin each tenant's data to a home region](https://www.cockroachlabs.com/product/geo-partitioning/) within a single database, without deploying separate regional clusters. Each row carries a region, and CockroachDB keeps its leaseholder and voting replicas there. Combined with placement controls (PLACEMENT RESTRICTED or super regions), this restricts all replicas of a row to its home region, which is the basis for data domiciling.\n\nThat matters for agents because they generate continuous database traffic: reasoning steps, memory writes, history retrieval, tenant sessions. For customers operating under GDPR transfer rules, LGPD, or PDPA, the physical location of tenant data is an architectural constraint, and often a prerequisite for enterprise procurement or expansion into new markets.\n\nThe traditional answer is separate database clusters per region, which multiplies infrastructure and application-level routing complexity as geographic coverage grows. With [ REGIONAL BY ROW](https://www.cockroachlabs.com/blog/regional-by-row/), adding an EU tenant becomes a data-placement decision rather than a new-database deployment.\n\nHere's how to extend the agent memory table to support data residency:\n\n*Note: the code below uses **REGIONAL BY ROW, crdb_internal_region, and gateway_region()**. These are CockroachDB-specific. This code will not run on standard PostgreSQL and will fail with syntax errors if you copy it directly. The pattern of pinning rows to a geographic region is available in other distributed SQL databases, but the syntax differs.*\n\n**Extending agent_memories for geo-partitioning**\n\nNow set the region when onboarding each tenant:\n\nThe EU enterprise customer's compliance team can now verify two things independently: Its data is isolated from other customers' data through RLS, and its regional placement is enforced through REGIONAL BY ROW. Both commonly arise in enterprise procurement security review.\n\n## What doesn't row-level security protect against?\n\nRLS at the database layer is one essential enforcement layer, but enterprise AI agent security requires controls across the broader agent stack. Shipping data isolation without understanding what it doesn't cover creates its own risks.\n\n**RLS doesn't protect against a tenant injecting into their own data.** A tenant can embed malicious instructions in their own records: instructions that the agent will execute with that tenant's permissions. Every external data source the agent reaches is a potential injection vector. Prompt sanitization, output validation, and tool call constraints handle this. Database isolation doesn't.\n\nLLM inference caching creates a separate cross-tenant attack surface. Shared prefix caches can expose information through Time-To-First-Token differences; research presented at NDSS 2025 demonstrated this timing side channel against Llama2-13B on an A100 GPU. If you operate your own inference layer, verify that KV caches are partitioned by tenant identity. Otherwise, cross-tenant prefix caching can leak information regardless of database isolation.\n\n__Agent memory__** and conversation history need the same treatment.** Conversation history stored in shared caches without tenant partitioning is a leak vector. Apply the same row-level isolation logic to your [ vector store](https://www.cockroachlabs.com/blog/agent-memory-database-cockroachdb-memori/).\n\n**Service account scope still matters.** Agents are provisioned with service accounts and API keys, often with broad scope, and those credentials persist for the life of the deployment. A prompt-injected agent doesn't need to steal credentials; it already holds them. A service account with read access to all tenants' data undermines database-level isolation. Scope every agent identity to minimum required permissions.\n\n## What are the principles for safer multi-tenant AI agent systems?\n\nSafer multi-tenant AI agent systems treat tenant isolation, data placement, and access control as infrastructure guarantees rather than application conventions.\n\n**Isolation is enforced, not remembered.** RLS makes the tenant constraint automatic rather than dependent on every application code path.\n\n**Geography is a first-class tenant attribute.** For enterprise SaaS, [ data residency](https://www.cockroachlabs.com/blog/multi-region-serverless-data-residency/) is often a procurement requirement.\n\n`REGIONAL BY ROW`\n\nenforces placement at the database layer, rather than through routing logic that can drift.**The security perimeter extends to the row.** A row-level database policy can't be bypassed by a forgotten WHERE clause or an agent persuaded to call a tool with attacker-controlled parameters.\n\nThe gap between a working demo and a system that holds up under real users, real data, and adversarial conditions is large. Most of that gap isn't in the AI. It's in the infrastructure around it.\n\n## When you don't need database-level tenant isolation\n\nNone of this is necessary for every AI agent deployment. If you're running a single-tenant deployment, an internal tool with exactly one customer, or an architecture where each tenant already gets a fully separate database or cluster with no shared schema, that isolation boundary already exists elsewhere, and adding RLS on top mostly adds policy-maintenance overhead without a corresponding security gain.\n\n**Implementation references:**\n\n**For engineers: **The [ CockroachDB Row-Level Security documentation](https://www.cockroachlabs.com/docs/v26.2/row-level-security) walks through enabling RLS, writing policies, and the multi-tenant isolation example end to end, including the FORCE ROW LEVEL SECURITY behavior that matters for privileged service accounts.\n\n**For teams planning a global agentic product:** Data residency with REGIONAL BY ROW and Super Regions is covered in the [ CockroachDB data domiciling guide](https://www.cockroachlabs.com/docs/v26.2/data-domiciling), including how to verify compliance programmatically.\n\nIf this article raised questions about your broader agent infrastructure picture, our [ context management post](http://cockroachlabs.com/blog/ai-agent-context-management/) covers the adjacent problem: memory architecture, concurrency under agent workloads, and what good observability looks like in practice.\n\nReady to put database-enforced tenant isolation into practice? [ Try CockroachDB free](https://cockroachlabs.cloud/signup?referralId=cc_nav_global) and start building with row-level security.\n\n**Props: **Thank you to Cockroach Labs' [ David Bressler](https://www.cockroachlabs.com/author/david-bressler/) for review of this article.\n\n*Quentin Packard is GM of Americas at Cockroach Labs, where he works with engineering and infrastructure leaders building production-grade agentic AI systems. He previously helped build Splunk's observability business and has worked across infrastructure automation, secrets management, and real-time data governance at HashiCorp and early-stage startups. His writing draws on direct conversations with enterprise teams navigating AI and data architecture in production.*\n\n## Sources\n\n__Noma Security, ForcedLeak: AI Agent Risks Exposed in Salesforce Agentforce____CyberScoop, Salesloft Drift attacks hit Cloudflare, Palo Alto Networks, Zscaler____NDSS 2025, Prompt Leakage via KV-Cache Sharing in Multi-Tenant LLM Serving__\n\n**AGENTS.md**\n\nDatabase configuration for multi-tenant agent workloads (CockroachDB):\n\n# Enable RLS and force it for privileged roles on every multi-tenant table\n\nALTER TABLE <table> ENABLE ROW LEVEL SECURITY;\n\nALTER TABLE <table> FORCE ROW LEVEL SECURITY;\n\n# Bind tenant context per-transaction, never per-connection in a pooled setup\n\nSET LOCAL app.tenant_id = '<tenant_uuid>';\n\n-- In driver code, use SELECT set_config('app.tenant_id', $1, true) instead:\n\n-- SET/SET LOCAL don't accept bind parameters, set_config does.\n\n# Every tenant-scoped table needs a matching policy on read AND write\n\nCREATE POLICY tenant_isolation ON <table>\n\nUSING (tenant_id = current_setting('app.tenant_id', true)::UUID)\n\nWITH CHECK (tenant_id = current_setting('app.tenant_id', true)::UUID);\n\n# Use a least-privilege role for agent tool execution; never the table owner or BYPASSRLS\n\nCREATE ROLE agent_worker WITH LOGIN;\n\nGRANT SELECT, INSERT, UPDATE ON <table> TO agent_worker;\n\n-- agent_worker must NOT have BYPASSRLS and must NOT be a member of admin --\n\n-- members of the admin role bypass RLS entirely, regardless of FORCE\n\n# Data residency: pin rows to region and set each tenant's home region at onboarding\n\n-- Use REGIONAL BY ROW; do not rely on application routing logic alone\n\n# Known gaps RLS does not cover\n\n-- CDC/changefeeds and COPY can bypass row-level policies on some paths; verify before use\n\n-- Cross-tenant KV-cache and vector-store reads are a separate isolation surface\n\n-- Prompt injection and service-account scope are not solved by RLS; enforce separately", "url": "https://wpnews.pro/news/multi-tenant-ai-agents-why-data-isolation-starts-at-the-database", "canonical_source": "https://cockroachlabs.com/blog/multi-tenant-ai-agents-why-data-isolation-starts-at-the-database", "published_at": "2026-08-11 00:00:00+00:00", "updated_at": "2026-08-11 19:47:42.520877+00:00", "lang": "en", "topics": ["ai-agents", "ai-safety", "ai-policy", "ai-infrastructure"], "entities": ["Cockroach Labs", "Salesforce Agentforce", "ServiceNow Now Assist", "Salesloft", "Drift", "Cloudflare", "Palo Alto Networks", "Noma Security"], "alternates": {"html": "https://wpnews.pro/news/multi-tenant-ai-agents-why-data-isolation-starts-at-the-database", "markdown": "https://wpnews.pro/news/multi-tenant-ai-agents-why-data-isolation-starts-at-the-database.md", "text": "https://wpnews.pro/news/multi-tenant-ai-agents-why-data-isolation-starts-at-the-database.txt", "jsonld": "https://wpnews.pro/news/multi-tenant-ai-agents-why-data-isolation-starts-at-the-database.jsonld"}}