What Is Multi-Tenancy?
Multi-tenancy is an architecture where a single instance of software serves multiple customers (tenants). Each tenant’s data is isolated, but they share the same application code, infrastructure, and often the same database.
Most modern SaaS products — Slack, Jira, Salesforce, Shopify — are multi-tenant. As a QA engineer working on SaaS products, understanding multi-tenancy testing is essential because the consequences of failures are severe: data leaks between tenants can result in lawsuits, lost customers, and regulatory penalties.
Multi-Tenant Architecture Patterns
| Pattern | Description | Testing Complexity |
|---|---|---|
| Shared database, shared schema | All tenants in one database with tenant_id column | Highest risk — one SQL error can expose all data |
| Shared database, separate schemas | One database, each tenant has its own schema | Medium risk — schema isolation provides some protection |
| Separate databases | Each tenant has its own database | Lower risk — strongest isolation |
| Hybrid | Mix of above based on tier (free=shared, enterprise=dedicated) | Complex — must test each pattern |
Critical Testing Areas
Data Isolation
The most important test category. Every data operation must be scoped to the current tenant:
API-level tests:
- Accessing another tenant’s resources by changing IDs in the URL
- Accessing another tenant’s resources by changing the tenant identifier in headers
- SQL injection attempts that could bypass tenant filtering
- Bulk operations that might accidentally include cross-tenant data
UI-level tests:
- Search results only show current tenant’s data
- Dropdown lists and autocomplete only suggest current tenant’s items
- Reports and dashboards only aggregate current tenant’s data
- Export/download only includes current tenant’s data
Tenant Configuration
Each tenant may customize:
- Branding: Logo, colors, domain, email templates
- Roles and permissions: Custom role definitions
- Workflows: Custom approval chains, notification rules
- Integrations: Third-party service connections
- Data fields: Custom fields on entities
Test that changes to Tenant A’s configuration do not affect Tenant B.
Subscription Tiers and Feature Gating
| Feature | Free | Pro | Enterprise |
|---|---|---|---|
| Users | 5 | 50 | Unlimited |
| Storage | 1GB | 50GB | 500GB |
| API access | No | Yes | Yes |
| SSO | No | No | Yes |
| Custom domain | No | Yes | Yes |
| Priority support | No | No | Yes |
Test matrix:
- Feature accessible on the correct tier
- Feature blocked on lower tiers (proper error message, not a crash)
- Upgrade immediately enables new features
- Downgrade properly restricts features (with grace period if applicable)
- Limits enforced correctly (cannot add 6th user on Free tier)
User Roles Within Tenants
Most SaaS apps have roles within each tenant:
| Role | Typical Permissions |
|---|---|
| Owner | Full control, billing, can delete tenant |
| Admin | User management, settings, data |
| Member | Create and edit own content |
| Viewer | Read-only access |
| Guest | Limited access to specific resources |
Test that each role can only perform allowed actions, especially:
- Members cannot access admin settings
- Viewers cannot modify data
- Guests cannot see resources outside their scope
- Removing a user’s role immediately revokes access
Exercise: Multi-Tenant SaaS Testing Scenarios
You are testing a project management SaaS application (similar to Jira/Asana) with three tiers: Free, Pro, and Enterprise.
Scenario 1: Data Isolation Testing
Create two tenant accounts: Tenant A (Acme Corp) and Tenant B (Beta Inc).
| Step | Action | Expected Result |
|---|---|---|
| 1 | As Tenant A, create project “Alpha” | Project visible only to Tenant A |
| 2 | As Tenant B, list all projects | “Alpha” is NOT visible |
| 3 | As Tenant B, try GET /api/projects/{alpha-id} | 404 Not Found (not 403 — do not reveal existence) |
| 4 | As Tenant A, search for “Alpha” | Found in results |
| 5 | As Tenant B, search for “Alpha” | Not found in results |
| 6 | As Tenant A, export all projects | Export contains only Tenant A’s projects |
| 7 | As Tenant B, create project also named “Alpha” | Allowed — tenants can have same-named resources |
Scenario 2: Feature Gating
| Step | Action | Expected Result |
|---|---|---|
| 1 | As Free tier, try to enable SSO | “Upgrade to Enterprise” prompt shown |
| 2 | As Free tier, try to add 6th user | “Upgrade to Pro” prompt with user limit message |
| 3 | As Pro tier, enable custom domain | Feature available, configuration works |
| 4 | As Pro tier, try to enable SSO | “Upgrade to Enterprise” prompt shown |
| 5 | Upgrade Free to Pro tier | New features immediately available |
| 6 | Downgrade Pro to Free tier | Features restricted, data preserved but inaccessible |
Scenario 3: Cross-Tenant Security
| Step | Action | Expected Result |
|---|---|---|
| 1 | As Tenant A admin, copy API endpoint for a resource | /api/tenants/a/projects/123 |
| 2 | As Tenant B admin, call that endpoint | 404 or 403 — no data leaked |
| 3 | As Tenant A, modify tenant_id in request header | Request rejected — tenant mismatch |
| 4 | As logged-out user, access tenant resources | 401 Unauthorized |
| 5 | As Tenant A user removed from tenant | Immediate access revocation |
Solution: Common Multi-Tenant Bugs
Bug 1: Cross-tenant data in search results Global search index did not filter by tenant_id. A user searching for a common term could see results from other tenants. Fix: Add tenant_id filter to all search queries.
Bug 2: 403 instead of 404 for cross-tenant resources Returning 403 (Forbidden) instead of 404 (Not Found) reveals that the resource exists in another tenant. This is information leakage. Fix: Always return 404 for cross-tenant access attempts.
Bug 3: Tenant branding cached across sessions After switching between tenants (for users who belong to multiple), the previous tenant’s logo and colors were cached and displayed. Fix: Invalidate UI cache on tenant switch.
Bug 4: Feature limit bypass via API The 5-user limit on Free tier was enforced in the UI but not in the API. Using direct API calls, a Free user could add unlimited users. Fix: Enforce limits at the API/database layer, not just UI.
Bug 5: Downgrade did not restrict features After downgrading from Pro to Free, custom domain setting remained active. Fix: Run feature restriction check on plan change and disable features above the new tier.
Bug 6: Admin of Tenant A could see Tenant B in admin panel The admin panel listed all tenants in a dropdown for support features. A tenant admin should only see their own tenant. Fix: Scope admin panel queries to current tenant.
Testing Strategy for SaaS Applications
Test Environment Setup
Maintain at least three tenant accounts in your test environment:
- Free tier tenant — for testing limits and upgrade prompts
- Pro tier tenant — for testing mid-tier features
- Enterprise tier tenant — for testing full feature set
Each tenant should have users in every role (Owner, Admin, Member, Viewer).
Automation Approach
// Parameterized test across tenants
const tenants = ['tenant-free', 'tenant-pro', 'tenant-enterprise'];
for (const tenant of tenants) {
test(`data isolation for ${tenant}`, async ({ request }) => {
const response = await request.get(`/api/projects`, {
headers: { 'X-Tenant-ID': tenant }
});
const projects = await response.json();
// Every project must belong to the current tenant
for (const project of projects) {
expect(project.tenantId).toBe(tenant);
}
});
}
Key Takeaways
- Data isolation is the highest-priority test area in multi-tenant applications — a leak can be catastrophic
- Always return 404 (not 403) for cross-tenant resource access to prevent information disclosure
- Feature gating must be enforced at the API layer, not just the UI
- Test subscription tier transitions: upgrades, downgrades, and what happens to data and features
- Maintain separate test tenants for each tier with users in every role
- Configuration changes in one tenant must never affect another tenant