Skip to main content

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
  • 🗂️ Tenant and TenantUser SQLModel models — ready-to-use ORM models with audit timestamps
  • ⚡ Redis caching — tenant data and user permissions are cached via permissions2fast-fastapi
  • 🔒 require_permission dependency — guard any route with a single line using the RBAC system from permissions2fast-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

Package PyPI Purpose
log2fast-fastapi PyPI Structured logging
pgsqlasync2fast-fastapi PyPI Async PostgreSQL connection manager
mailing2fast-fastapi PyPI SMTP email sender
oauth2fast-fastapi PyPI JWT Auth + User management
permissions2fast-fastapi PyPI RBAC + Redis permission cache

📋 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 Category for generic categorization (not PermissionCategory)
  • Can be reused across different entity types

License

MIT © Angel Daniel Sanchez Castillo

Metadata

Release files for tenants2fast-fastapi 0.7.4

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for tenants2fast-fastapi 0.7.4
File Size Uploaded
tenants2fast_fastapi-0.7.4.tar.gz 67.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for tenants2fast-fastapi 0.7.4
File Interpreter ABI Platform
tenants2fast_fastapi-0.7.4-py3-none-any.whl Python 3 none any Details

Total release size: 128.9 kB

Release files / tenants2fast_fastapi-0.7.4.tar.gz

Download URL tenants2fast_fastapi-0.7.4.tar.gz
Size 67.5 kB
Tags Source
SHA-256 checksum
How to use checksums
3d8038c47950a7a41eb82bd571771f6cdd51b6dfa46446eebcd4bfe90f6f8a40
BLAKE2b-256 checksum
How to use checksums
a29145c7b2da1b01dc082e15b0c6d156bdd408e07d5a56ea59a2ca8e6a8d31dc
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.4-py3-none-any.whl

Download URL tenants2fast_fastapi-0.7.4-py3-none-any.whl
Size 61.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
ce0de69e3663632f42e8a0865e6cd4c8fc1a7c8fd795c200f63c83048ecbc88d
BLAKE2b-256 checksum
How to use checksums
b9ab366b117c016faa1ec5d54094455b71779ad790c126d3a1ea8260b1704cb8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.9

Release history Release notifications | RSS feed

0.8.0

2 release files

This release

0.7.4 This release

2 release files

0.7.3

2 release files

0.7.2

2 release files

0.7.1

2 release files

0.7.0

2 release files

0.6.3

2 release files

0.6.2

2 release files

0.6.1

2 release files

0.6.0

2 release files

0.5.1

2 release files

0.5.0

2 release files

0.4.1

2 release files

0.4.0

2 release files

0.3.2

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.7

2 release files

0.2.6

2 release files

0.2.5

2 release files

0.2.4

2 release files

0.2.3

2 release files

0.2.2

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page