tenants2fast-fastapi
🏢 Multi-tenancy management for FastAPI — tenant isolation, JWT-aware middleware, and permission-gated endpoints, all wired up in minutes.
Part of the *2fast-fastapi ecosystem: oauth2fast-fastapi → permissions2fast-fastapi → tenants2fast-fastapi.
📖 Conventions reference: this package follows the 2fast-handbook for ecosystem conventions (structure, versioning, README, commits, release).
Features
- 🔐 JWT-aware
TenantMiddleware— extracts user from Bearer token and sets tenant context automatically on every request - 🏗️ Isolated tenant databases — each tenant gets its own PostgreSQL database, created and initialized at runtime
- 🗂️
TenantandTenantUserSQLModel models — ready-to-use ORM models with audit timestamps - ⚡ Redis caching — tenant data and user permissions are cached via
permissions2fast-fastapi - 🔒
require_permissiondependency — guard any route with a single line using the RBAC system frompermissions2fast-fastapi
Installation
pip install tenants2fast-fastapi
Or with uv:
uv add tenants2fast-fastapi
Quick Start
from fastapi import Depends, FastAPI
from tenant2fast_fastapi import (
TenantMiddleware,
get_current_tenant,
get_current_user,
require_permission,
)
app = FastAPI()
# 1. Register the middleware
app.add_middleware(TenantMiddleware)
# 2. Use dependencies in your endpoints
@app.get("/me/tenant")
async def my_tenant(tenant=Depends(get_current_tenant)):
return {"name": tenant.name, "slug": tenant.slug}
@app.get("/reports", dependencies=[Depends(require_permission("/reports", "GET"))])
async def reports(user=Depends(get_current_user)):
return {"user": user.email}
See examples/basic_usage.py for a more complete example.
Configuration
All settings use the TENANT_ prefix and can be provided via environment variables or a .env file.
| Variable | Default | Description |
|---|---|---|
TENANT_DB_PREFIX |
tenant_ |
Prefix for per-tenant database names |
TENANT_SUPERUSER_DB__HOSTNAME |
localhost |
PG host for superuser operations |
TENANT_SUPERUSER_DB__PORT |
5432 |
PG port |
TENANT_SUPERUSER_DB__USERNAME |
postgres |
PG superuser username |
TENANT_SUPERUSER_DB__PASSWORD |
postgres |
PG superuser password |
TENANT_SUPERUSER_DB__NAME |
postgres |
Default DB for superuser connection |
TENANT_MAX_TENANT_CONNECTIONS |
5 |
Connection pool size per tenant |
In addition, all variables required by oauth2fast-fastapi (JWT, DB connections, mail) and permissions2fast-fastapi (Redis) must be set — see their respective READMEs.
Public API
from tenant2fast_fastapi import (
Tenant, # SQLModel ORM model (table: tenants)
TenantUser, # Many-to-many User ↔ Tenant (table: tenant_users)
TenantMiddleware, # Starlette BaseHTTPMiddleware
get_current_tenant, # FastAPI dependency → Tenant
get_current_user, # FastAPI dependency → User (from oauth2fast-fastapi)
require_permission, # Dependency factory → checks RBAC + cache
create_tenant_database, # async — creates a PG database for a tenant
get_tenant_engine, # returns (cached) AsyncEngine for a tenant DB
initialize_tenant_schema, # async — runs SQLModel.metadata.create_all on tenant DB
)
Development
# Clone and install in editable mode with dev + test dependencies
git clone https://github.com/AngelDanielSanchezCastillo/tenants2fast-fastapi
cd tenants2fast-fastapi
uv sync --group dev --group test
# Copy .env and adjust to your local setup
cp .env .env.local # or just edit .env directly
# Run tests (requires PostgreSQL + Redis)
uv run pytest tests/ -v
# Build distribution
uv build
Related Packages
📋 Naming Conventions
This package follows consistent naming conventions for models and database tables:
Model Classes (Python)
- Singular PascalCase
- Examples:
User,Role,Permission,Category,Route
Database Tables
- Plural snake_case
- Examples:
users,roles,permissions,categories,routes
Many-to-Many Join Tables
- Plural snake_case on both table names
- Alphabetical order of the two table names
- Examples:
role_users(r < u),permission_roles(p < r),permission_routes(p < r)
Tenant-Local vs Auth DB Models
- Auth DB:
Tenant(table:tenants),TenantUser(table:tenant_users) - maps users ↔ tenants - Tenant DB:
User,Role,Permission,Category,Route- local tenant entities
Generic Categories
- Use
Categoryfor generic categorization (notPermissionCategory) - Can be reused across different entity types
License
Metadata
Release files for tenants2fast-fastapi 0.7.3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| tenants2fast_fastapi-0.7.3.tar.gz | 58.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| tenants2fast_fastapi-0.7.3-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 114.9 kB
Release files / tenants2fast_fastapi-0.7.3.tar.gz
| Download URL | tenants2fast_fastapi-0.7.3.tar.gz |
|---|---|
| Size | 58.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
c4b95cfed23b4c75a62b98f1d2bf6ce453de1d7f504f709e08694de879ae5868
|
|
BLAKE2b-256 checksum How to use checksums |
f295418e55b6d0481064e255fbefaf08dcb1e94a511a1a3d7f91ab703b2fe4f5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.9
|
Release files / tenants2fast_fastapi-0.7.3-py3-none-any.whl
| Download URL | tenants2fast_fastapi-0.7.3-py3-none-any.whl |
|---|---|
| Size | 56.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
3710b642804520563209e473f62511415d1b642011435d349cb03d82ad50085f
|
|
BLAKE2b-256 checksum How to use checksums |
8f0ae2757c8f63a7c99e307043bb269de08a1b5fd743a08ba0a56b62c9982b31
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.9
|