KEY INSIGHT
User management in SaaS requires three-tier hierarchy—organizations, workspaces, and individual users—with role assignments at each level.
AI SaaS products serve different customer types. A freelance developer and a corporation with 500 employees both need accounts. The data model must accommodate both patterns without forcing a rigid structure.
The recommended model has three entities: `Organization` (the paying customer), `Workspace` (logical grouping for projects or teams), and `User` (individual accounts that may belong to multiple organizations).
```python
from sqlalchemy import Column, String, DateTime, ForeignKey, Table
from sqlalchemy.orm import relationship
import uuid
class Organization(Base):
__tablename__ = "organizations"
id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
name = Column(String(255), nullable=False)
subscription_tier = Column(String(50), nullable=False, default="free")
created_at = Column(DateTime, default=datetime.utcnow)
# Relationships
workspaces = relationship("Workspace", back_populates="organization")
memberships = relationship("OrganizationMembership", back_populates="organization")
class Workspace(Base):
__tablename__ = "workspaces"
id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
organization_id = Column(String(36), ForeignKey("organizations.id"), nullable=False)
name = Column(String(255), nullable=False)
organization = relationship("Organization", back_populates="workspaces")
api_keys = relationship("ApiKey", back_populates="workspace")
class User(Base):
__tablename__ = "users"
id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
email = Column(String(255), unique=True, nullable=False)
password_hash = Column(String(255), nullable=False)
created_at = Column(DateTime, default=datetime.utcnow)
memberships = relationship("OrganizationMembership", back_populates="user")
class OrganizationMembership(Base):
__tablename__ = "organization_memberships"
id = Column(String(36), primary_key=True)
user_id = Column(String(36), ForeignKey("users.id"), nullable=False)
organization_id = Column(String(36), ForeignKey("organizations.id"), nullable=False)
role = Column(String(50), nullable=False) # 'owner', 'admin', 'member', 'viewer'
user = relationship("User", back_populates="memberships")
organization = relationship("Organization", back_populates="memberships")
```
Role hierarchies need careful definition. Organization-level roles control billing, user management, and subscription changes. Workspace-level roles control API key creation, usage monitoring, and model access. A user might be an organization owner but a workspace viewer.