Tenant Isolation Tiers: Pool Versus Silo Controls on Shared AWS Accounts

Tenant Isolation Tiers: Pool Versus Silo Controls on Shared AWS Accounts
8 views
Not every SaaS customer needs a dedicated account—but enterprise tenants do need stronger than WHERE tenant_id = ?. The unfair advantage is an explicit tier ladder (pool → bridge → silo) with IAM, KMS, and network controls that escalate with contract risk.
⚡ TL;DR: Pool = shared tables + enforced tenant predicates + app authz; Bridge = per-tenant KMS CMK + IAM path + noisy-neighbor limits; Silo = dedicated account/VPC/cell. Encode the tier in provisioning, not wiki tribal knowledge. Pair with Cell-Based Architecture on AWS and Bedrock Retrieval Filters: Tenant Isolation.

Tenant Isolation Tiers: production guidance

Tier Compute Data Keys When
Pool Shared ECS/Lambda Shared table, tenant_id Account CMK SMB / free
Bridge Shared + reserved concurrency Shared table + per-tenant S3 prefix Per-tenant CMK Mid-market
Silo Dedicated cell/account Dedicated DB/bucket Tenant-owned CMK Enterprise / regulated
typescript
// ✅ Central guard — every data access carries TenantContext
export type Tier = "pool" | "bridge" | "silo";

export interface TenantContext {
 tenantId: string;
 tier: Tier;
 kmsKeyArn: string;
}

export function assertTenantRow(row: { tenant_id: string }, ctx: TenantContext) {
 if (row.tenant_id !== ctx.tenantId) {
 throw new Error("tenant_isolation_violation"); // ✅ fail closed
 }
}

IAM and KMS for bridge tier

json
// ✅ S3 prefix isolation with session tags / inline session policy
{
 "Effect": "Allow",
 "Action": ["s3:GetObject", "s3:PutObject"],
 "Resource": "arn:aws:s3:::saas-data/${aws:PrincipalTag/tenant_id}/*"
}
python
# ✅ Encrypt with per-tenant CMK; never default to account key for bridge+
import boto3
s3 = boto3.client("s3")

def put_object(ctx, key: str, body: bytes) -> None:
 s3.put_object(
 Bucket="saas-data",
 Key=f"{ctx.tenant_id}/{key}",
 Body=body,
 ServerSideEncryption="aws:kms",
 SSEKMSKeyId=ctx.kms_key_arn, # ✅ tenant CMK
 )
❌ Relying only on application filters without IAM/KMS boundaries for bridge/silo — one SQLi-shaped bug becomes a multi-tenant breach.

Noisy neighbors and blast radius

Pool tiers still need bulkheads: per-tenant rate limits (Multi-Tenant Rate Limits), reserved Lambda concurrency, and cell placement so a silo outage does not take pool customers.

Closing checklist

✅ Dos – ✅ Document tier → controls matrix in an ADR – ✅ Provision KMS keys and IAM paths automatically on upgrade – ✅ Fail closed on tenant mismatch – ✅ Load-test noisy-neighbor controls per tier – ✅ Align contracts/DPA with actual technical tier ❌ Don’ts – ❌ Don’t sell “dedicated” while sharing CMKs – ❌ Don’t skip integration tests that attempt cross-tenant reads – ❌ Don’t put all enterprise silos in one cell – ❌ Don’t let support tooling bypass tenant guards without audit

Related reading

Last updated on September 11, 2026 Related: AWS Multi-Tenant SaaS Control Plane Architecture: API Gateway, ECS, DynamoDB, Step Functions, and EventBridge; AWS Lambda Coding Agent Sandbox: Safe Tool Isolation for LLM Agents; Day 23: Metadata Filters and Tenant Isolation.

Watch: 100 Days of AI on YouTube

Short videos from CheatCoders, one AI engineering topic per day.

Open the playlist on YouTube · CheatCoders on YouTube

Deep-dive PDF

Get the expanded guide for this post — extra diagrams-style checklists, failure modes, and a production walkthrough. Free when you subscribe to CheatCoders.

Already subscribed? or open the subscribe page.


Discover more from CheatCoders

Subscribe to get the latest posts sent to your email.

Comments

No comments yet. Why don’t you start the discussion?

Leave a comment

No account needed. Name and email are optional.