Architecture Advice Needed – Multi-Tenant Business Platform

I'm looking for architectural feedback from experienced software engineers and architects.

Current Context

We have a business management platform used by multiple companies.

Tech stack:

  • Frontend: React + Vite + Tailwind + customized Shadcn/UI

  • Backend: Django + DRF

  • Database: SQL Server

  • Async jobs: Celery + Redis

  • Storage: MinIO

  • Mobile: Capacitor

  • Reverse Proxy: Traefik + Nginx

The platform contains several business domains:

Collections & Finance

  • Clients

  • Documents

  • Payments

  • Unpaid invoices

  • Risk management

  • Validation workflows

Human Resources

  • Employees

  • Attendance

  • Expenses

  • Documents

  • Commissions

  • Tasks

Commercial & Sales

  • Objectives

  • Validation cycles

  • Sales tracking

The backend is organized as a modular monolith composed of roughly 40+ Django apps.


How The Platform Works Today

The platform is used by several independent companies.

Each company currently has:

  • Its own domain/subdomain

  • Its own branding

  • Its own logo

  • Its own SQL Server database

  • Its own ERP database integration

Example:

client-a.platform.com
client-b.platform.com
client-c.platform.com

Functionally, all companies use nearly the same application.

Differences are mostly:

  • Branding

  • Configuration

  • Data

  • ERP connection settings


Current Deployment Model

Today, each company has its own deployment stack.

For every company we run:

Frontend
Backend
Celery Worker
Celery Beat
Redis
Nginx

Which means:

5 companies = 5 stacks
20 companies = 20 stacks
100 companies = 100 stacks

The codebase is identical across all deployments.

Only configuration and tenant-specific settings change.


Current Architecture

Positive Aspects

  • Clear business domains

  • Modular monolith structure

  • JWT authentication

  • Celery background jobs

  • Shared codebase

  • Strong domain organization

Current Challenges

  • Limited automated testing

  • No mature CI/CD pipeline yet

  • Operational overhead grows with every new company

  • Some cross-domain dependencies remain

  • Branding is deployment-specific rather than tenant-driven


Important Technical Constraint

Many models currently define tables like:

db_table = f"[{settings.SQL_SERVER_DB}].[dbo].[TABLE_NAME]"

The database name is resolved at application startup.

This means the application is effectively bound to a specific database when the process starts.

Serving multiple tenant databases from the same running application would require architectural changes.


What We Want To Achieve

Move from:

One deployment per company

To:

One shared platform
One deployment
Multiple tenant databases
Multiple ERP databases
Dynamic branding
Dynamic configuration

Conceptually:

                Platform
                    |
      --------------------------------
      |              |              |
   Client A       Client B       Client C
      |              |              |
     DB A           DB B           DB C
    ERP A          ERP B          ERP C

Goals:

  • Single codebase

  • Single deployment process

  • Easier onboarding of new companies

  • Dynamic branding based on tenant

  • Strong tenant isolation

  • Lower operational cost

  • Ability to scale to dozens or hundreds of companies


Questions

  1. Would you keep the modular monolith architecture or move toward microservices?

  2. Would you keep a database-per-tenant model or choose another tenancy strategy?

  3. What risks do you see with dynamic database routing in Django?

  4. Have you implemented a similar architecture?

  5. With a team of 2–5 developers, what would be your priority roadmap for the next 12 months?

  6. What major architectural risks might we be underestimating?

Any feedback, criticism, alternative approaches, or real-world experiences would be greatly appreciated.

It sounds like you are potentially trying to rewrite your entire application. If you're looking at switching to a shared-tenancy model and possibly breaking into microservices, these are large changes, especially if you need to do this without affecting your existing customers. There are a huge number of non-technical constraints here – "what would be your priority roadmap" is something that depends a lot on your company's specific needs.

To put a little context on it, in my previous job my main project was designing and supporting a microservice platform with the goal of eventually migrating our monolith application to it while still keeping customers running and adding new features, and after six years the monolith application hadn't really been reduced at all.

I'd suggest actually hiring an architect to design this for you; they can give you advice based on what your company is actually doing and your actual code base. Stack Overflow is much more for specific programming questions. What sort of answer are you hoping to get from the broader community?

In broad strokes, it sounds like configuration and settings vary by tenant. Your first big shift is too make sure branding and data connections are all configurable. Next I would work on the infrastructure of the application so passing a tenant ID allows you to look up relevant configs.

It's almost like you need N+1 databases. That "+1" database acts more like a registry of tenants that provides basic configuration information — a tenant module, so to speak.

Once the non-user facing components are changed to fetch tenant configs, work on the user-facing components. This is where end user authentication presents some challenges. You will need some way to associate users with a tenant. A single sign on scenario would work, and I imagine you can associate tenants with email domain names; there's your link.

It feels like you need to separate end user authentication and tenant configuration into their own modules. Upon successful authentication, get the tenant configuration from the tenants module. Maybe store the tenant ID in a secure cookie marked HttpOnly so every request has access to that Id.

This will be a big structural shift. It's really hard to give meaningful advice for something like this unless you are deeply embedded in the codebase and organization. At that point, I'm your coworker, not some stranger on the Internet.

Definitely don't move to micro services. That just adds layers of complexity for no benefit if you don't need the ability to scale and deploy modules independently.

My advice would be to make it work with multiple tenants on a single DB and single ERP system.

Having a dynamic connection string is a pain, affects performance and doesn't really give you any more security.

Setting up the multiple DBs, although much easier in these days of containers is still a pain and maintaining them all is worse.

A single set of infrastructure allows that fully automated client onboarding you want to be able to scale.

You can break out duplicate stacks for big customers if required.

If you move to PostgreSQL, you can use django-tenants this works with schema-based tenants. So each table is replicated per tenant in a separate schema.

It uses the hostname to determine what the tenant is, and has some tools to migrate all schemas.

This thus means you have a single web server that serves all tenants, but depending on the hostname, it routes to a different schema, and works thus with one connection to the database.

It does that by injecting a set search_path into the query mechanism, that thus specifies what schemas to search for.

It will require some work to migrate all the data of the different databases in the PostgreSQL database. Especially the fact that migrating from a different database dialect always has a few caveats.

The advantage is that normally you then no longer have to maintain the tenants separately: you can run migrations on all tenants at the same time, and you thus have one single code base to maintain.

Вернуться на верх