Jump to content

Multi-Tenancy in FastAPI: A Complete Guide

From JOHNWICK
Revision as of 22:33, 13 December 2025 by PC (talk | contribs) (Created page with "Building modern SaaS applications often requires serving multiple customers (tenants) from the same application while keeping their data securely isolated. This concept is called multi-tenancy. In this article, we will dive deep into multi-tenancy in FastAPI, explore different approaches, and implement a practical example to understand it better. What is Multi-Tenancy? Multi-tenancy is an architectural pattern where a single application serves multiple customers (te...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

Building modern SaaS applications often requires serving multiple customers (tenants) from the same application while keeping their data securely isolated. This concept is called multi-tenancy. In this article, we will dive deep into multi-tenancy in FastAPI, explore different approaches, and implement a practical example to understand it better.


What is Multi-Tenancy? Multi-tenancy is an architectural pattern where a single application serves multiple customers (tenants). Each tenant might represent a company, department, or user group.

There are two main approaches to multi-tenancy:

  • Database-per-tenant
  • Each tenant has a completely separate database.
  • Provides strong isolation.
  • Harder to scale when the number of tenants grows.

2. Shared-database with tenant separation

  • All tenants share the same database, but data is separated using a tenant_id column.
  • Easier to scale and maintain.
  • Requires strict application-level enforcement of data isolation.


Why Use Multi-Tenancy in FastAPI?

  • Scalability: One codebase can handle multiple customers.
  • Cost efficiency: Shared infrastructure reduces hosting costs.
  • Maintainability: Deploy, monitor, and upgrade only one application instead of multiple.


Implementing Multi-Tenancy in FastAPI Let’s build an example where we implement a shared-database multi-tenancy approach in FastAPI using SQLAlchemy.


Step 1: Project Setup Install required dependencies:

pip install fastapi uvicorn sqlalchemy psycopg2-binary


Step 2: Database Model with Tenant Separation We’ll create a users table where each user is linked to a tenant via tenant_id.

from sqlalchemy import Column, Integer, String, ForeignKey
from sqlalchemy.orm import declarative_base, relationship

Base = declarative_base()

class Tenant(Base):
    __tablename__ = "tenants"
    id = Column(Integer, primary_key=True, index=True)
    name = Column(String, unique=True)
    users = relationship("User", back_populates="tenant")

class User(Base):
    __tablename__ = "users"
    id = Column(Integer, primary_key=True, index=True)
    name = Column(String)
    tenant_id = Column(Integer, ForeignKey("tenants.id"))
    tenant = relationship("Tenant", back_populates="users")

Here:

  • Tenant table stores tenant information.
  • User table is linked to tenants through tenant_id.


Step 3: Middleware for Tenant Identification We need to identify which tenant is making a request. One common approach is to use a custom header (X-Tenant-ID).

from fastapi import FastAPI, Request, HTTPException

app = FastAPI()

@app.middleware("http")
async def tenant_middleware(request: Request, call_next):
    tenant_id = request.headers.get("X-Tenant-ID")
    if not tenant_id:
        raise HTTPException(status_code=400, detail="X-Tenant-ID header missing")
    
    request.state.tenant_id = tenant_id
    response = await call_next(request)
    return response

This middleware ensures that every request includes a tenant ID.


Step 4: Dependency for Tenant-Aware Queries We’ll use request.state.tenant_id to filter tenant-specific data.

from fastapi import Depends

def get_tenant_id(request: Request):
    return request.state.tenant_id


Step 5: Tenant-Specific Endpoints Now, let’s implement endpoints to create and fetch users for a specific tenant.

from fastapi import Depends
from sqlalchemy.orm import Session
from database import get_db  # assume we have a DB session dependency
from models import User

@app.post("/users/")
def create_user(name: str, db: Session = Depends(get_db), tenant_id: str = Depends(get_tenant_id)):
    user = User(name=name, tenant_id=tenant_id)
    db.add(user)
    db.commit()
    db.refresh(user)
    return user

@app.get("/users/")
def list_users(db: Session = Depends(get_db), tenant_id: str = Depends(get_tenant_id)):
    users = db.query(User).filter(User.tenant_id == tenant_id).all()
    return users

Here:

  • create_user ensures that new users are always linked to the current tenant.
  • list_users ensures that only tenant-specific users are retrieved.


Step 6: Testing the Multi-Tenancy

Create a Tenant

INSERT INTO tenants (name) VALUES ('Tenant A'), ('Tenant B');

Add Users for Tenant A

curl -X POST "http://localhost:8000/users/" -H "X-Tenant-ID: 1" -d "name=Alice" curl -X POST "http://localhost:8000/users/" -H "X-Tenant-ID: 1" -d "name=Bob"

Add Users for Tenant B

curl -X POST "http://localhost:8000/users/" -H "X-Tenant-ID: 2" -d "name=Charlie"

Fetch Users for Tenant A

curl -X GET "http://localhost:8000/users/" -H "X-Tenant-ID: 1"

  1. Returns: Alice, Bob

Fetch Users for Tenant B

curl -X GET "http://localhost:8000/users/" -H "X-Tenant-ID: 2"

  1. Returns: Charlie


Best Practices for Multi-Tenancy in FastAPI

  • Always enforce tenant filtering in every database query.
  • Use middleware to extract tenant identifiers from headers or subdomains.
  • Consider database-per-tenant if you need strict data isolation.
  • Secure tenant identification — don’t allow clients to manipulate tenant IDs directly; use authentication tokens linked to tenants.
  • Scalability — monitor database size and query performance as tenants increase.


Conclusion Multi-tenancy is a powerful design pattern for SaaS applications. In this blog, we explored how to implement tenant-aware APIs in FastAPI using a shared-database approach. By enforcing tenant separation at the middleware and query level, we can efficiently serve multiple tenants while maintaining data security. For large-scale SaaS applications, carefully evaluate between database-per-tenant and shared-database multi-tenancy based on your isolation, cost, and scalability requirements.

Read the full article here: https://medium.com/@rameshkannanyt0078/multi-tenancy-in-fastapi-a-complete-guide-e6923702490a