Sebastien LatoSingle-user apps are simple. But real products eventually need: multiple accounts team...
Single-user apps are simple.
But real products eventually need:
Without proper architecture, this leads to:
This post shows how to design a multi-tenant architecture in SwiftUI that:
Every piece of data must belong to a tenant.
If you don’t know which account owns a piece of state, your architecture is already unsafe.
A tenant represents a data boundary.
struct Tenant {
let id: UUID
let name: String
let role: Role
}
enum Role {
case personal
case member
case admin
}
This could represent:
Never store global user data.
Bad:
class AppState {
var user: User
var projects: [Project]
}
Correct:
class AppState {
var activeTenant: Tenant
var tenantStores: [UUID: TenantStore]
}
Each tenant has its own isolated state.
final class TenantStore: ObservableObject {
@Published var user: User
@Published var projects: [Project]
@Published var settings: TenantSettings
}
This ensures:
Switching tenants should:
Example:
func switchTenant(to tenant: Tenant) {
activeTenant = tenant
currentStore = tenantStores[tenant.id]
}
Never reuse old state across tenants.
Services must be tenant-aware.
Bad:
apiClient.fetchProjects()
Correct:
apiClient.fetchProjects(for: tenantID)
Or inject a tenant-scoped client:
TenantAPIClient(tenantID: tenant.id)
Every request must carry tenant context.
Persist data per tenant:
/Storage
/tenant_1
projects.db
/tenant_2
projects.db
Or use namespaced keys:
"tenant_\(id)_settings"
Never share storage across tenants.
You must test:
Multi-tenant bugs are subtle and dangerous.
Tenants may have different roles.
Example:
if tenant.role == .admin {
showAdminPanel()
}
Never assume capabilities across tenants.
Avoid:
These cause the worst production bugs.
Think:
Tenant
→ Tenant Store
→ Tenant Services
→ Tenant Storage
→ Tenant UI
Not:
“There’s just one user”
A proper multi-tenant architecture gives you:
If your app ever needs teams or organizations,
multi-tenant architecture is not optional.