Are you building a multi-tenant application with Flask and SQLAlchemy? In this guide, we’ll show you how to efficiently set up multi-tenancy where each tenant has its own database, all while using subdomain-based identification. This approach provides data isolation for each tenant and scales well as you add more tenants.
What is Multi-Tenancy?
Multi-tenancy is a software architecture pattern where multiple clients (tenants) share the same application, but each tenant has its own isolated data. This can be achieved by either using a single database with tenant-specific schemas or by assigning each tenant its own database. In this tutorial, we’ll focus on the latter, where each tenant has a separate database.
Key Benefits of Using Separate Databases for Each Tenant
- Data Isolation: With separate databases, you completely isolate data between tenants.
- Scalability: Adding new tenants is easier as each tenant gets its own database.
- Security: In case of a breach in one database, others remain secure.
Step 1: Create a Master Database for Tenant Management
The master database will store details for each tenant, including their respective database connection strings. Let’s first define the Tenant
model that represents tenants in the master database.
Step 2: Configure Flask with SQLAlchemy
In this step, we’ll set up Flask to connect to the master database, which manages all tenants. This connection will be used to look up tenants based on their subdomain.
Step 3: Identify Tenants from Subdomain
Each tenant will access the application using a unique subdomain (e.g., tenant1.yourapp.com
). We’ll use Flask’s @app.before_request
to identify which tenant is making the request by extracting the subdomain and fetching the corresponding database URI from the master database.
Step 4: Set Up Dynamic Database Connections
Once the tenant is identified, we need to dynamically connect to the appropriate tenant-specific database for each request. To achieve this, we’ll create a helper function to manage database sessions.
Step 5: Use Context Manager for Transaction Management
To ensure smooth transaction handling, we’ll implement a session_scope()
function that provides a transactional scope around a series of operations. It automatically commits if successful and rolls back in case of errors.
Step 6: Query Tenant-Specific Data
We can now query data specific to each tenant. Every route that interacts with the database will use the session_scope()
context manager to ensure the correct tenant database is used.
Step 7: Testing the Multi-Tenancy Setup
To test the multi-tenancy setup:
- Add tenant records to the master database with unique subdomains and database names.
- Set up tenant-specific databases on your system.
- Access the app from different subdomains to see each tenant’s isolated data.
For example, visiting tenant1.yourapp.com
will connect to Tenant 1’s database, while tenant2.yourapp.com
will connect to Tenant 2’s database.
Conclusion
In this tutorial, we walked through setting up multi-tenancy in Flask using SQLAlchemy, with each tenant using its own database. By using subdomain-based tenant identification, you can scale your application as new tenants join, ensuring both security and data isolation.