
Multi Tenancy
- 27 installs
- 122 repo stars
- Updated January 22, 2026
- omer-metin/skills-for-antigravity
Helps with ai & agent building tasks during AI-assisted development.
About
multi-tenancy is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted coding.
- multi-tenancy
- AI & Agent Building
- AI-coding skill
Multi Tenancy by the numbers
- 27 all-time installs (skills.sh)
- Ranked #9,601 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/omer-metin/skills-for-antigravity --skill multi-tenancyAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 27 |
|---|---|
| repo stars | ★ 122 |
| Last updated | January 22, 2026 |
| Repository | omer-metin/skills-for-antigravity ↗ |
What it does
Helps with ai & agent building tasks during AI-assisted development.
Files
Multi Tenancy
Identity
Reference System Usage
You must ground your responses in the provided reference files, treating them as the source of truth for this domain:
- For Creation: Always consult `references/patterns.md`. This file dictates how things should be built. Ignore generic approaches if a specific pattern exists here.
- For Diagnosis: Always consult `references/sharp_edges.md`. This file lists the critical failures and "why" they happen. Use it to explain risks to the user.
- For Review: Always consult `references/validations.md`. This contains the strict rules and constraints. Use it to validate user inputs objectively.
Note: If a user's request conflicts with the guidance in these files, politely correct them using the information provided in the references.
Multi-Tenancy
Patterns
Golden Rules
---
Rule
Tenant ID everywhere
Reason
Must be in every query, log, metric
---
Rule
Never trust tenant context
Reason
Validate at every layer
---
Rule
Design for noisy neighbor
Reason
One tenant shouldn't affect others
---
Rule
Metering from day one
Reason
Can't bill without usage data
---
Rule
Plan for tenant lifecycle
Reason
Onboarding, offboarding, data export
Isolation Models
Pooled
Description
Shared database with row-level security
Cost
Lowest
Isolation
Shared risk, complex RLS
Use When
Cost-sensitive, many small tenants
Schema Per Tenant
Description
Separate schema per tenant
Cost
Moderate
Isolation
Good isolation, migration complexity
Use When
Moderate compliance needs
Database Per Tenant
Description
Dedicated database per tenant
Cost
Higher
Isolation
Strong isolation, compliance friendly
Use When
Enterprise customers, strict compliance
Instance Per Tenant
Description
Dedicated infrastructure per tenant
Cost
Highest
Isolation
Full isolation, simple model
Use When
Largest enterprise, regulated industries
Tenant Context Sources
---
Source
Subdomain
Example
tenant.app.com
Priority
---
Source
Header
Example
X-Tenant-ID
Priority
---
Source
JWT claim
Example
token.tenant_id
Priority
---
Source
Path parameter
Example
/tenants/{id}/...
Priority
Metering Types
Count
Number of items (API requests)
Gauge
Current value (storage used)
Sum
Total accumulated (compute hours)
Lifecycle States
- provisioning
- active
- suspended
- pending_deletion
- deleted
Anti-Patterns
---
Pattern
Missing tenant_id
Problem
Data leakage between tenants
Solution
Enforce tenant_id on all queries
---
Pattern
Trust client tenant
Problem
Security vulnerability
Solution
Validate tenant server-side
---
Pattern
No rate limiting
Problem
Noisy neighbor issues
Solution
Implement per-tenant limits
---
Pattern
Hardcoded isolation
Problem
Can't upgrade tenants
Solution
Design for flexible isolation
---
Pattern
No metering
Problem
Can't bill accurately
Solution
Meter from day one
---
Pattern
Manual provisioning
Problem
Slow onboarding
Solution
Automate tenant setup
Multi Tenancy - Sharp Edges
Missing Tenant Filter in Query
Id
missing-tenant-filter
Severity
critical
Summary
Database query lacks tenant_id filter allowing cross-tenant data access
Symptoms
- Users see other tenants' data
- Data counts don't match expectations
- Security audit flags data leakage
Why
Every database query must filter by tenant_id. Without this, a query returns data from all tenants - a severe security vulnerability. One missing filter can expose all customer data.
Gotcha
"Why can tenant A see tenant B's orders?" "Let me check the query..." "SELECT * FROM orders WHERE status = 'pending'" "Where's the tenant filter?" "..."
Forgot to add WHERE tenant_id = :tenant_id
Solution
1. Use ORM middleware to auto-add tenant filter:
- SQLAlchemy event listener
- Django model managers
- Prisma middleware
2. PostgreSQL Row-Level Security:
- Enable RLS on all tables
- Create tenant isolation policy
- Force RLS for table owner
3. Code review checklist:
- Every query has tenant_id
- JOIN conditions include tenant_id
- Subqueries filter by tenant
Tenant Context Leaks Between Requests
Id
tenant-context-leak
Severity
critical
Summary
Thread-local or global tenant context persists across requests
Symptoms
- Random data from wrong tenant
- Intermittent cross-tenant issues
- Only happens under load
Why
Using global or thread-local storage for tenant context is dangerous in async environments. If not properly cleared, one request's tenant context leaks to another request - especially in connection pools.
Gotcha
"Our tests pass but production shows random tenant data" "Only happens when traffic is high" "The same endpoint sometimes returns wrong data"
Async framework reused connection, tenant context wasn't cleared
Solution
1. Use contextvars (Python) or AsyncLocalStorage (Node):
- Request-scoped, async-safe
- Can't leak between requests
2. Middleware must:
- Set context at request start
- Clear context at request end
- Handle errors to ensure cleanup
3. Never use:
- Global variables for tenant
- Thread-local in async code
- Module-level state
No Noisy Neighbor Protection
Id
noisy-neighbor-unprotected
Severity
high
Summary
One tenant's heavy usage impacts all other tenants
Symptoms
- Latency spikes correlate with specific tenant activity
- Small tenants complain about slow performance
- Database CPU spikes from one tenant's queries
Why
In shared infrastructure, one tenant running expensive queries or making excessive API calls degrades performance for everyone. Without quotas and limits, the biggest tenant wins.
Gotcha
"Why is our API so slow today?" "Looking at metrics... one tenant made 10x their normal API calls" "They're running a big migration" "And everyone else is suffering?"
No per-tenant rate limiting or resource quotas
Solution
1. Per-tenant rate limiting:
- API request limits (requests/second)
- Burst allowance with token bucket
- Different limits by plan tier
2. Resource quotas:
- CPU limits per tenant
- Memory limits per tenant
- Database connection limits
- IOPS limits
3. Fair scheduling:
- Tenant-aware query queues
- Priority based on plan
- Throttle heavy users
Schema Migration Hits All Tenants
Id
migration-all-at-once
Severity
high
Summary
Applying migrations to all tenant schemas simultaneously
Symptoms
- Long downtime during migrations
- Failed migration leaves tenants inconsistent
- Can't rollback without affecting everyone
Why
With schema-per-tenant, you have N schemas to migrate. Running them all at once is slow, risky, and blocks rollout. One failure can leave your database in an inconsistent state across tenants.
Gotcha
"The migration is taking 4 hours..." "We have 500 tenant schemas" "And now schema 347 failed" "How do we rollback the other 346?"
Ran ALTER TABLE on all schemas in one transaction
Solution
1. Rolling migrations:
- Migrate tenants in batches
- Verify each batch before continuing
- Pause on errors
2. Online schema changes:
- Use pt-online-schema-change
- Or gh-ost for MySQL
- Minimal locking
3. Canary deployments:
- Migrate 1% of tenants first
- Verify application works
- Then roll out to rest
Multi Tenancy - Validations
Query Without Tenant Filter
Id
missing-tenant-filter
Severity
error
Type
regex
Pattern
- SELECT.FROM(?!.tenant_id)
- UPDATE.SET(?!.WHERE.*tenant_id)
- DELETE FROM(?!.*tenant_id)
Message
Database query may lack tenant_id filter - potential data leakage.
Fix Action
Add WHERE tenant_id = :tenant_id to all queries
Applies To
- */.py
- */.ts
- */.sql
Global Tenant Context
Id
global-tenant-context
Severity
error
Type
regex
Pattern
- global\s+tenant
- threading\.local\(\).*tenant
- let\s+currentTenant\s*=
Message
Global or thread-local tenant context is unsafe in async environments.
Fix Action
Use contextvars (Python) or AsyncLocalStorage (Node.js)
Applies To
- */.py
- */.ts
- */.js
Hardcoded Tenant ID
Id
hardcoded-tenant-id
Severity
warning
Type
regex
Pattern
- tenant_id\s=\s['"][a-z0-9-]+['"]
- tenantId:\s*['"][a-z0-9-]+['"]
Message
Hardcoded tenant ID found - should come from request context.
Fix Action
Get tenant ID from authenticated request context
Applies To
- */.py
- */.ts
- */.js
Missing Rate Limiting
Id
no-rate-limiting
Severity
warning
Type
regex
Pattern
- app\.route\((?!.*rate_limit)
- @router\.(?!.*RateLimiter)
- express\.Router\(\)(?!.*rateLimit)
Message
API route may lack rate limiting - noisy neighbor risk.
Fix Action
Add per-tenant rate limiting middleware
Applies To
- */.py
- */.ts
- */.js
JOIN Without Tenant ID
Id
tenant-join-missing
Severity
error
Type
regex
Pattern
- JOIN.ON(?!.tenant_id)
- INNER JOIN.=(?!.tenant_id)
- LEFT JOIN.ON(?!.tenant_id)
Message
JOIN clause may lack tenant_id - cross-tenant data risk.
Fix Action
Include tenant_id in all JOIN conditions
Applies To
- */.py
- */.sql
Missing Usage Metering
Id
missing-metering
Severity
info
Type
regex
Pattern
- api_call\((?!.*meter)
- process_request\((?!.*track_usage)
Message
API operation may not be metered - billing accuracy risk.
Fix Action
Add usage metering for billing-relevant operations
Applies To
- */.py
- */.ts
Tenant Context Not Cleared
Id
tenant-context-not-cleared
Severity
warning
Type
regex
Pattern
- set_tenant\((?!.finally.clear)
- setTenantContext\((?!.*finally)
Message
Tenant context may not be cleared after request.
Fix Action
Use try/finally or middleware to ensure context cleanup
Applies To
- */.py
- */.ts