Multi-Tenant SaaS on Azure: Architecture, Identity, and Data Isolation
Introduction
[Explain business drivers: serve multiple customers from shared infrastructure while ensuring security, compliance, and cost efficiency.]
Multi-Tenancy Models
| Model | Isolation Level | Cost Efficiency | Complexity |
|---|---|---|---|
| Silo (Dedicated) | High | Low | Low |
| Pool (Shared) | Low | High | Medium |
| Hybrid | Medium | Medium | High |
Reference Architecture
Step-by-Step Guide
Step 1: Tenant Onboarding
[Provision tenant record in master DB; configure B2C policy or federated IdP]
Step 2: Identity Strategy
Option A: Entra ID B2C with Custom Policies
<TechnicalProfile Id="AAD-UserReadUsingObjectId">
<Metadata>
<Item Key="UserPrincipalName">user@tenant.onmicrosoft.com</Item>
</Metadata>
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="tenantId" PartnerClaimType="extension_TenantId" />
</OutputClaims>
</TechnicalProfile>
Option B: Multi-Tenant App Registration
[Configure app to accept users from any organization; resolve tenant from claims]
Step 3: Request Context Middleware
public class TenantMiddleware
{
private readonly RequestDelegate _next;
public TenantMiddleware(RequestDelegate next) => _next = next;
public async Task InvokeAsync(HttpContext context, ITenantResolver resolver)
{
var tenantId = await resolver.ResolveTenantAsync(context);
context.Items["TenantId"] = tenantId;
await _next(context);
}
}
Step 4: Data Isolation Patterns
Cosmos DB: Partition by TenantId
var container = cosmosClient.GetContainer("orders", "orders");
var query = new QueryDefinition("SELECT * FROM c WHERE c.tenantId = @tenantId")
.WithParameter("@tenantId", tenantId);
Azure SQL: Row-Level Security
CREATE FUNCTION dbo.fn_tenantAccessPredicate(@TenantId uniqueidentifier)
RETURNS TABLE
WITH SCHEMABINDING
AS
RETURN SELECT 1 AS fn_accessResult
WHERE @TenantId = CAST(SESSION_CONTEXT(N'TenantId') AS uniqueidentifier);
CREATE SECURITY POLICY TenantFilter
ADD FILTER PREDICATE dbo.fn_tenantAccessPredicate(TenantId) ON dbo.Orders;
Step 5: Feature Flagging per Tenant
[Use Azure App Configuration with tenant labels; control feature access dynamically]
Step 6: Monitoring & Cost Allocation
[Tag resources with tenant dimension; query Application Insights with tenant filter]
requests
| extend TenantId = tostring(customDimensions["TenantId"])
| summarize RequestCount = count(), AvgDuration = avg(duration) by TenantId
| order by RequestCount desc
Step 7: Throttling & Fair Use
[Implement rate limiting per tenant using API Management policies or Redis sliding window]
Security & Compliance
- Cross-Tenant Leakage Prevention: Validate tenant context on every data access.
- Encryption: Transparent Data Encryption (SQL), encryption at rest (Cosmos).
- Audit Logging: Centralize tenant activity logs in Log Analytics workspace.
- Data Residency: Use regional deployment stamps for GDPR/compliance requirements.
Scaling Strategies
| Challenge | Solution |
|---|---|
| Hot tenant | Dedicated shard or reserved capacity |
| Global reach | Azure Front Door + regional stamps |
| Cost attribution | Resource tagging + chargeback reports |
| Noisy neighbor | Request throttling + isolated compute tier |
CI/CD Pipeline Considerations
- Blue-green deployment per stamp
- Rolling updates with canary tenant validation
- Database migration coordination across shards
Troubleshooting
Issue: Tenant data visible to another tenant
Solution: Audit query filters; enforce RLS; add integration tests per tenant
Issue: High Azure costs
Solution: Rightsize SKUs; consolidate underutilized tenants into shared pool
Issue: Identity federation breaks
Solution: Test B2C custom policies in sandbox; validate claims mapping
Best Practices
- Start with pool model; migrate heavy tenants to silo as needed.
- Abstract tenant resolution early in middleware pipeline.
- Automate tenant provisioning and configuration.
- Enforce least privilege across tenant boundaries.
Key Takeaways
- Pool model maximizes cost efficiency; silo model ensures strict isolation.
- Identity federation centralizes authentication complexity.
- Data isolation via partition keys or RLS prevents cross-tenant leakage.
- Monitoring and cost allocation are critical for SaaS sustainability.
Next Steps
- Implement tenant lifecycle automation
- Add self-service tenant portal
- Explore geo-replication for global tenants
Additional Resources
How will you architect your next SaaS offering?