Back to articles

Isolated per-tenant storage for multi-tenant AI agent applications

How to isolate per-tenant storage in multi-tenant AI agent apps: storage-layer scope, microVM execution, credential brokering and a disk per tenant.

10 min read

Isolated per-tenant storage for multi-tenant AI agent applications is an infrastructure commitment. It works only when storage, execution, and credentials enforce the same tenant boundary. An application filter cannot make that promise on its own, especially when the application’s newest worker can write code, call tools, and wander through a filesystem without asking directions.

Why per-tenant storage isolation is an infrastructure problem, not an application-layer one

Teams that build traditional SaaS often think of isolation in terms of application filters and row-level policies. Agents push that model past the primary database. They generate and execute code, call tools autonomously, and use filesystems, databases, and external APIs without a human navigating a constrained interface. The interface is no longer the fence.

The specific failure is that tenant scope exists at login but disappears as work passes through tools, queues, caches, artifacts, credentials, and logs. A tenant_id in a prompt or model-generated argument describes intent. Even friendly resource names can cause collisions. If two tenants both have resources called production, orders, or main, selecting a name from context can silently resolve to the wrong object. No attacker is required for that mistake, only shared infrastructure that treats a familiar name as sufficient authority.

Where cross-tenant leakage actually originates in agent memory and retrieval systems

Leakage rarely starts in the primary record store. It starts in the retrieval and enrichment paths around it. A shared embeddings index can return another tenant’s vectors when a similarity query omits the tenant filter. A shared knowledge graph can merge two employees called “Alex Chen” into one canonical node, creating a connection neither tenant authorized.

Background summarization, reindexing, and graph enrichment introduce another route. These jobs often iterate over shared records with elevated credentials, then write results without reapplying the tenant predicate. Because an agent’s execution environment often holds tenant context implicitly, that context can disappear when work leaves the interactive session. Logs and traces create a quieter exposure when raw prompts or recall payloads enter an unscoped debugging system. Signed URLs can leak data too when the service signs whatever object key the agent gives it without first checking who owns the object.

The three levels of storage isolation and when each is the right fit

Shared tables with row-level policy cost little to run, and adding a tenant takes just an insert. Their protection depends on the policy, connection role, and alternate access paths being correctly scoped. Row-level security does more than an application WHERE clause. However, a path that bypasses the policy and omits the tenant predicate can expose shared data.

Schema-per-tenant storage adds a separate namespace inside one database, making cross-tenant queries structurally harder while adding migration and connection work. Database-per-tenant storage separates databases and credentials, but provisioning, pooling, backups, and migrations grow with tenant count. Object storage has similar choices, with prefixed keys in a shared bucket, separate namespaces, or separate buckets with separate credentials. Each gives a different boundary and costs a different amount to run.

The decision is not a security beauty contest. Higher isolation fits regulatory requirements, unusually large tenants, customer-managed encryption, or independent restore needs. Most production platforms use a mix of logical scoping, dedicated storage, and per-deployment isolation for different groups of customers. Amazon Bedrock AgentCore is one managed option that surfaces multi-tenant design concerns, but the service choice does not remove the need to choose those boundaries deliberately.

Why object storage path isolation must be enforced at the storage layer, not the application layer

A path such as gs://{bucket}/tenants/{tenant_id}/sessions/ provides the minimum useful partition for tenant files. The prefix is not permission by itself. When many tenant disks or mounts point at one bucket, bucket-resource policies must enforce conditions on the tenant identifier. Otherwise, isolation still depends on application code remembering to pass the right prefix, which is a naming convention wearing a security badge.

With storage-enforced scope, dropping an application filter must not broaden access into another tenant’s files. Signed URL issuance needs the same discipline, with object ownership checked before signing. Copying datasets into a shared sandbox weakens this arrangement because the copies leave the tenant path and inherit the execution environment’s boundary. Mounting storage in place instead preserves that path and reduces copying costs.

Archil implements this pattern with per-tenant disks that mount existing S3, GCS, R2, Azure Blob, or S3-compatible buckets as POSIX filesystems without migration. The bucket remains the source of truth, with synchronization in both directions. AWS S3 Files, generally available on April 7, 2026, is a comparable approach to reducing the need to copy data into compute environments for AWS-native stacks. The useful distinction is where access is enforced.

How execution isolation interacts with storage isolation, and why containers alone are not sufficient

Storage isolation fails if agents that share an execution environment can reach each other’s mounted paths. A partitioned bucket cannot repair an overexposed process space. Standard containers limit resources and isolate processes, but containers on a node share the host kernel. A container escape through that kernel can expose the host and neighboring tenants, widening the blast radius beyond the customer whose code ran.

MicroVMs add a dedicated guest kernel behind hardware virtualization. Firecracker and Kata Containers provide this approach, which is the recommended default for arbitrary, unreviewed agent-generated code. AgentCore runs each user session in a dedicated microVM with isolated CPU, memory, and filesystem. In Archil’s sandboxes, each workload runs in a dedicated Firecracker microVM with its own Linux kernel and persistent root disk.

gVisor intercepts syscalls through a user-space kernel, offering container-like density with a narrower security boundary than hardware virtualization. Hardened containers fit trusted, platform-written jobs, so a hybrid deployment can match isolation to workload trust. GPUs require explicit planning because Firecracker lacks GPU passthrough, making options such as gVisor or Cloud Hypervisor relevant when agents need GPUs for inference.

Credential handling as the third layer where tenant isolation must hold

A sandbox command as ordinary as printenv can expose credentials injected into environment variables. That is not much of a treasure hunt. If credentials for another tenant are present, agent-generated code can read those too, despite an otherwise isolated filesystem and microVM.

The recommended pattern is credential brokering at the network boundary. A tool worker receives only a credential reference it is authorized to resolve, while an egress proxy adds the secret to outgoing requests. Provider credentials need tenant-owned references rather than platform-wide ones, so revocation does not break unrelated customers. OAuth grants and tool sessions likewise belong to the tenant and user they act for.

Egress policy complements brokering with default-deny rules and explicit allowances that restrict destinations even if code obtains a secret. Archil’s Free plan uses a managed allowlist covering package registries, git hosts, container registries, OS package mirrors, and model APIs, while Developer plans and above support custom firewall rules, including deny-by-default, and credential brokering. A shared provider account still requires per-tenant accounting and revocation.

Binding tenant identity through the full agent execution pipeline

The mechanism joining these controls is authenticated tenant identity. Tenant scope must come from the session or application credential before resource input is accepted, never from a model-generated tenant_id. Even a globally unique resource ID identifies an object whose access must be authorized under the current tenant.

Before each tool call runs, it needs a chain that links the authenticated session to the tenant and delegated scope, then to server-side authorization. Denials must be recorded rather than swallowed, so the agent does not mistake a policy decision for a transient failure. Queue messages need to get their tenant scope from authenticated server context, and workers must reauthorize when they pick up those messages. Elevated queue access is not a substitute for that check.

Caches need non-user-controlled tenant identifiers in both keys and invalidation. Rate and spend limits also need tenant and agent partitions, though neither replaces authorization. NIST’s zero-trust framing makes the governing principle clear. Access is a per-request decision based on identity and resource. Internal tool calls and background workers do not earn broad access merely by being inside the platform.

Persistent, per-tenant workspaces that survive across sessions and scale to many agents simultaneously

A workspace can stay strictly isolated without being rebuilt for every session. Agents that work across conversations need to keep their packages and working files when they stop and restart. The requirement is a tenant-scoped disk. In systems such as Archil, isolated persistent sandboxes with per-tenant disks also make background jobs less likely to operate accidentally on a neighbor’s files because the filesystem available to the job is already scoped.

Persistence can support several agents without merging tenant namespaces. A planner and executor agents can share an additional disk while retaining separate kernels, so the coordination surface is the filesystem. Root disks are exclusively owned by default, while additional disks can use read-only or conditional mounts. Multi-attach does not itself weaken the tenant boundary because microVM and credential isolation still govern access.

Shared writes nevertheless need deliberate coordination. Archil uses delegation-based write ownership through [archil checkout](https://docs.archil.com/concepts/sharing-disks) in place of traditional advisory POSIX locks across clients. Writes become durable when fsync returns, with background synchronization when a backing data source is configured. Managed disks have no user-owned backing bucket by default, and other parts of the platform can use an S3-compatible API to reach artifacts without going through the sandbox.

Branching and checkpointing per-tenant workspaces for parallel agent attempts and safe rollback

A separate persistent disk gives each tenant an independent rollback and parallelization unit. Shared storage has to copy data to give a workspace that same independent fork. Archil’s disk checkpoints and branches complete in tens of milliseconds regardless of disk size. This disk operation is faster than taking a snapshot of the full running sandbox’s CPU and memory state.

Before a high-risk step, the recommended pattern is to checkpoint the tenant disk, run the action, evaluate its output, and then commit or revert. Recovery need not begin after the damage. The branch gives an attempt that could destroy data a contained place to fail without using the tenant’s working environment as scratch paper.

The same mechanism supports parallel attempts on one tenant dataset. A platform can make N branches, run N versions of an agent, compare their outputs, and keep the winning branch without making N copies of the data. Agents in separate branches do not see each other’s intermediate writes. The benefit is not simply speed, but a workspace boundary that makes experimentation and rollback practical without mixing unrelated work.

Deletion, observability, and the operational practices that complete the isolation commitment

Provisioning is only the start of the isolation obligation. For deletion, engineers must account for databases, cached values, queued work, artifacts, memories, indexes, browser sessions, sandboxes, credentials, logs, backups, and active operations. New work must stop and credentials must be revoked before data deletion begins. The deletion path needs to be resumable and idempotent, with immediate deletion, scheduled expiry, and legal or security retention decided in advance.

Observability needs its own rules for who can access it as the platform runs. Tenant fields make logs and traces useful for investigation, but those fields do not restrict who can search them. Prompts, tool arguments, and results need redaction before export to shared observability systems. A well-intentioned internal dashboard can still be a privileged route across tenants.

Bring-your-own-bucket storage keeps the residency decision with the customer. With Archil’s bidirectional synchronization to the tenant’s bucket, revoking platform access leaves the customer’s data in their own account rather than requiring deletion of a separate platform copy. That does not dispose of logs, credentials, queued jobs, or the other lifecycle surfaces. The infrastructure promise holds only while authorization, audit, and deletion keep enforcing it, including after the agent has stopped talking.

Hunter Leath

Founder & CEO