Marketplace
database-isolation
Use when implementing tenant data isolation in databases. Covers Row-Level Security (RLS), schema-per-tenant, database-per-tenant patterns with EF Core, SQL Server, PostgreSQL, and Cosmos DB implementations.
allowed_tools: Read, Glob, Grep, Task
$ Installieren
git clone https://github.com/melodic-software/claude-code-plugins /tmp/claude-code-plugins && cp -r /tmp/claude-code-plugins/plugins/saas-patterns/skills/database-isolation ~/.claude/skills/claude-code-plugins// tip: Run this command in your terminal to install the skill
SKILL.md
name: database-isolation description: Use when implementing tenant data isolation in databases. Covers Row-Level Security (RLS), schema-per-tenant, database-per-tenant patterns with EF Core, SQL Server, PostgreSQL, and Cosmos DB implementations. allowed-tools: Read, Glob, Grep, Task
Database Isolation Patterns
Implementation patterns for isolating tenant data at the database level, from logical to physical isolation.
When to Use This Skill
- Implementing tenant data isolation in a new SaaS application
- Choosing between RLS, schema-per-tenant, or database-per-tenant
- Configuring EF Core for multi-tenant scenarios
- Preventing cross-tenant data access
- Optimizing database performance in multi-tenant systems
Isolation Spectrum
Isolation Level vs Cost/Complexity:
Logical (Shared) Physical (Isolated)
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโบ
โโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโ
โ Row-Level โ Schema โ Database โ Server โ
โ Security โ per Tenant โ per Tenant โ per Tenant โ
โโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโค
โ Lowest Cost โ โ โ Highest Cost โ
โ Shared DB โ Shared DB โ Dedicated DB โ Dedicated โ
โ Shared Schemaโ Dedicated โ โ Server โ
โ โ Schema โ โ โ
โโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโค
โ Scale: 1M+ โ Scale: 10K โ Scale: 1K โ Scale: 100s โ
โ tenants โ tenants โ tenants โ tenants โ
โโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโ
Pattern 1: Row-Level Security (RLS)
Concept
Single Database, Shared Schema, Logical Isolation:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Shared Database โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ Orders Table โ โ
โ โ โโโโโโโฌโโโโโโโโโโโฌโโโโโโโโโโโโโโฌโโโโโโโโโฌโโโโโโโโโโโโโโ โ โ
โ โ โ id โ tenant_idโ customer โ amount โ created_at โ โ โ
โ โ โโโโโโโผโโโโโโโโโโโผโโโโโโโโโโโโโโผโโโโโโโโโผโโโโโโโโโโโโโโค โ โ
โ โ โ 1 โ acme โ John Doe โ 99.00 โ 2025-01-15 โ โ โ
โ โ โ 2 โ contoso โ Jane Smith โ 149.00 โ 2025-01-15 โ โ โ
โ โ โ 3 โ acme โ Bob Wilson โ 49.00 โ 2025-01-16 โ โ โ
โ โ โ 4 โ startup โ Alice Brown โ 199.00 โ 2025-01-16 โ โ โ
โ โ โโโโโโโดโโโโโโโโโโโดโโโโโโโโโโโโโโดโโโโโโโโโดโโโโโโโโโโโโโโ โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ RLS Policy: Only show rows where tenant_id = current_tenant โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Tenant "acme" sees only rows 1 and 3
Tenant "contoso" sees only row 2
Tenant "startup" sees only row 4
SQL Server Implementation (PascalCase Convention)
Step 1: Add TenantId to all tables
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ ALTER TABLE Orders ADD TenantId NVARCHAR(50) NOT NULL; โ
โ CREATE INDEX IX_Orders_TenantId ON Orders(TenantId); โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Step 2: Create security predicate function
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ CREATE FUNCTION dbo.fn_TenantAccessPredicate โ
โ (@TenantId NVARCHAR(50)) โ
โ RETURNS TABLE โ
โ WITH SCHEMABINDING โ
โ AS RETURN โ
โ SELECT 1 AS AccessGranted โ
โ WHERE @TenantId = CAST(SESSION_CONTEXT(N'TenantId') โ
โ AS NVARCHAR(50)) โ
โ OR SESSION_CONTEXT(N'TenantId') IS NULL; โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Step 3: Create security policy
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ CREATE SECURITY POLICY dbo.TenantSecurityPolicy โ
โ ADD FILTER PREDICATE โ
โ dbo.fn_TenantAccessPredicate(TenantId) ON dbo.Orders, โ
โ ADD BLOCK PREDICATE โ
โ dbo.fn_TenantAccessPredicate(TenantId) ON dbo.Orders โ
โ AFTER INSERT, AFTER UPDATE; โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Step 4: Set context per request
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ EXEC sp_set_session_context @key=N'TenantId', โ
โ @value=@CurrentTenantId; โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
PostgreSQL Implementation
Step 1: Enable RLS on table
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ ALTER TABLE orders ENABLE ROW LEVEL SECURITY; โ
โ ALTER TABLE orders FORCE ROW LEVEL SECURITY; โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Step 2: Create policy
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ CREATE POLICY tenant_isolation_policy ON orders โ
โ USING (tenant_id = current_setting('app.current_tenant'))โ
โ WITH CHECK (tenant_id = โ
โ current_setting('app.current_tenant')); โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Step 3: Set context per connection
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ SET app.current_tenant = 'acme'; โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
EF Core Global Query Filters
Application-Level RLS (Defense in Depth):
DbContext Configuration:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ public class AppDbContext : DbContext โ
โ { โ
โ private readonly ITenantContext _tenantContext; โ
โ โ
โ protected override void OnModelCreating(ModelBuilder mb) โ
โ { โ
โ // Apply filter to all tenant entities โ
โ mb.Entity<Order>() โ
โ .HasQueryFilter(o => โ
โ o.TenantId == _tenantContext.TenantId); โ
โ โ
โ mb.Entity<Customer>() โ
โ .HasQueryFilter(c => โ
โ c.TenantId == _tenantContext.TenantId); โ
โ } โ
โ } โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Key Points:
- EF Core filters applied BEFORE SQL generation
- Cannot be bypassed by LINQ queries
- Use IgnoreQueryFilters() only for admin scenarios
- Combine with database RLS for defense in depth
When to Use RLS
โ
Ideal For:
- B2C SaaS with many tenants (10,000+)
- Homogeneous tenant requirements
- Cost-sensitive deployments
- Simple compliance requirements
- Minimal schema customization needs
โ Avoid When:
- Strict compliance (HIPAA, PCI with audit requirements)
- Tenants need schema customization
- Performance isolation critical
- Data sovereignty requirements
Pattern 2: Schema-Per-Tenant
Concept
Single Database, Separate Schemas:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Shared Database โ
โ โ
โ โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโ โ
โ โ Schema: acme โ โ Schema: contoso โ โ Schema: startup โ โ
โ โ โ โ โ โ โ โ
โ โ โโโโโโโโโโโโโโโ โ โ โโโโโโโโโโโโโโโ โ โ โโโโโโโโโโโโโโโ โ โ
โ โ โ Orders โ โ โ โ Orders โ โ โ โ Orders โ โ โ
โ โ โ Customers โ โ โ โ Customers โ โ โ โ Customers โ โ โ
โ โ โ Products โ โ โ โ Products โ โ โ โ Products โ โ โ
โ โ โ (Custom tbl)โ โ โ โโโโโโโโโโโโโโโ โ โ โ (Custom tbl)โ โ โ
โ โ โโโโโโโโโโโโโโโ โ โ โ โ โโโโโโโโโโโโโโโ โ โ
โ โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโ โ
โ โ
โ Each schema is isolated, can have custom tables/columns โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Implementation Pattern
Connection/Schema Selection:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Option A: Schema in Connection String โ
โ - Set default schema per connection โ
โ - Works with connection pooling โ
โ โ
โ Option B: Schema per Query โ
โ - Prefix table names: [acme].Orders โ
โ - More flexible, slightly more complex โ
โ โ
โ Option C: EF Core Schema Configuration โ
โ - Set HasDefaultSchema() in OnModelCreating โ
โ - Dynamic based on tenant context โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Migrations Considerations
Migration Strategy:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Approach 1: Apply to All Schemas (Homogeneous) โ
โ - Loop through all tenant schemas โ
โ - Apply same migration to each โ
โ - Must be backward compatible โ
โ โ
โ Approach 2: Per-Tenant Migrations (Heterogeneous) โ
โ - Track migration state per tenant โ
โ - Allows tenant-specific schema variations โ
โ - More complex to manage โ
โ โ
โ Recommendation: Start homogeneous, allow customization โ
โ only for enterprise tier โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
When to Use Schema-Per-Tenant
โ
Ideal For:
- Medium number of tenants (100-10,000)
- Some schema customization needed
- Better isolation than RLS, lower cost than DB-per-tenant
- Easier backup/restore per tenant than RLS
โ Avoid When:
- Very large number of tenants (schema count limits)
- Strict performance isolation needed
- Complete infrastructure isolation required
- Per-tenant backup/restore at database level needed
Pattern 3: Database-Per-Tenant
Concept
Dedicated Database per Tenant:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ SQL Server Instance โ
โ โ
โ โโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโ โ
โ โ DB: db_acme โ โ DB: db_contoso โ โ DB: db_startup โ ... โ
โ โ โ โ โ โ โ โ
โ โ Full schema โ โ Full schema โ โ Full schema โ โ
โ โ Own backups โ โ Own backups โ โ Own backups โ โ
โ โ Own security โ โ Own security โ โ Own security โ โ
โ โ Custom config โ โ Custom config โ โ Custom config โ โ
โ โโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโ โ
โ โ
โ Elastic Pool for cost optimization (optional) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Connection String Resolution
Tenant Catalog โ Connection String (SQL Server - PascalCase):
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ TenantCatalog Table: โ
โ โโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ TenantId โ ConnectionString โ โ
โ โโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค โ
โ โ acme โ Server=sql1;Database=db_acme;... โ โ
โ โ contoso โ Server=sql1;Database=db_contoso;... โ โ
โ โ startup โ Server=sql2;Database=db_startup;... โ โ
โ โโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ Resolution Flow: โ
โ 1. Request arrives with TenantId โ
โ 2. Lookup connection string in catalog (cached) โ
โ 3. Create/reuse connection from tenant-specific pool โ
โ 4. Execute query on tenant's database โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Elastic Pools (Azure SQL)
Cost Optimization with Elastic Pools:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Without Elastic Pool: โ
โ - 10 tenants ร S2 ($75/month) = $750/month โ
โ - Each DB has dedicated 50 DTU โ
โ - Underutilized during off-peak โ
โ โ
โ With Elastic Pool: โ
โ - 1 pool with 200 eDTU = $300/month โ
โ - 10 databases share the pool โ
โ - Burst to 50 eDTU per DB when needed โ
โ - Average utilization across tenants โ
โ โ
โ Savings: 60% ($450/month) โ
โ โ
โ Best For: Variable, unpredictable workloads โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
When to Use Database-Per-Tenant
โ
Ideal For:
- Enterprise customers with strict compliance
- Tenants needing complete data isolation
- Per-tenant backup/restore requirements
- Custom schema per tenant
- Data sovereignty requirements
- Tenants with significantly different workloads
โ Avoid When:
- Many small tenants (cost prohibitive)
- Fast provisioning needed (<1 minute)
- Minimal compliance requirements
- Cost-sensitive market
Cosmos DB Multi-Tenancy
Partition Key Strategy
Cosmos DB Isolation Levels:
Level 1: Partition Key per Tenant (Logical)
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Container: orders โ
โ Partition Key: /tenantId โ
โ โ
โ โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โ
โ โ Partition: โ โ Partition: โ โ Partition: โ โ
โ โ acme โ โ contoso โ โ startup โ โ
โ โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โ
โ โ
โ Pros: Lowest cost, automatic scaling โ
โ Cons: Shared RU/s, noisy neighbor possible โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Level 2: Container per Tenant
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Database: myapp โ
โ โ
โ โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โ
โ โ Container: โ โ Container: โ โ Container: โ โ
โ โ acme-orders โ โcontoso-ordersโ โstartup-ordersโ โ
โ โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โ
โ โ
โ Pros: Per-tenant RU/s limits, RBAC per container โ
โ Cons: Container limits (500K), higher management โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Level 3: Database per Tenant
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Cosmos Account: myapp โ
โ โ
โ โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โ
โ โ Database: โ โ Database: โ โ Database: โ โ
โ โ acme โ โ contoso โ โ startup โ โ
โ โ โโcontainers โ โ โโcontainers โ โ โโcontainers โ โ
โ โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โ
โ โ
โ Pros: Full isolation, RBAC per database โ
โ Cons: Higher cost, more management overhead โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Defense in Depth
Layered Security
Multi-Layer Isolation:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Layer 1: Network (outer) โ
โ - VNet isolation for Silo tenants โ
โ - Private endpoints โ
โ - Firewall rules โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Layer 2: Database โ
โ - RLS policies (SQL Server/PostgreSQL) โ
โ - Partition isolation (Cosmos DB) โ
โ - Connection-level authentication โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Layer 3: Application โ
โ - EF Core global query filters โ
โ - Tenant context validation middleware โ
โ - Business logic checks โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Layer 4: API (inner) โ
โ - Request-level tenant validation โ
โ - Authorization checks โ
โ - Audit logging โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Principle: No single layer failure should expose data
Decision Framework
Quick Selection
Tenant Count and Requirements โ Pattern:
< 100 tenants + Compliance needed โ Database-per-tenant
< 100 tenants + Cost-sensitive โ Schema-per-tenant
100-10,000 tenants โ Schema-per-tenant or RLS
> 10,000 tenants โ RLS (mandatory)
Customization needed?
- None: RLS
- Some: Schema-per-tenant
- Full: Database-per-tenant
Compliance level?
- SOC 2/GDPR basic: RLS with audit logging
- HIPAA/PCI: Database-per-tenant minimum
- Government/Financial: Database-per-tenant + network isolation
Anti-Patterns
| Anti-Pattern | Problem | Solution |
|---|---|---|
| No TenantId index | Slow queries, table scans | Add composite indexes |
| Trusting client TenantId | Data leakage | Server-side validation |
| Missing RLS on some tables | Partial isolation | Apply to ALL tenant tables |
| Hard-coded connection strings | No per-tenant isolation | Dynamic resolution |
| Ignoring query filters in admin | Admin bypass leaks data | Audit admin operations |
Related Skills
tenancy-models- Pool/Silo/Bridge architecture patternstenant-context-propagation- Passing context across servicesnoisy-neighbor-prevention- Resource isolation techniques
References
- Load
references/row-level-security.mdfor detailed RLS implementations - Load
references/schema-per-tenant.mdfor schema isolation patterns - Load
references/database-per-tenant.mdfor dedicated database patterns
Last Updated: 2025-12-26
Repository

melodic-software
Author
melodic-software/claude-code-plugins/plugins/saas-patterns/skills/database-isolation
3
Stars
0
Forks
Updated3d ago
Added1w ago