# Scaling Mautic: How We Achieved Multi-Tenancy (Single Code, Multi-DB)

**URL:** <https://forum.mautic.org/t/scaling-mautic-how-we-achieved-multi-tenancy-single-code-multi-db/38145>\
**Category:** General Discussion\
**Created:** [April 23, 2026, 9:06am UTC](https://forum.mautic.org/t/scaling-mautic-how-we-achieved-multi-tenancy-single-code-multi-db/38145 "2026-04-23T09:06:32Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![vwesley](https://avatars.discourse-cdn.com/v4/letter/v/ebca7d/32.png) [@vwesley](https://forum.mautic.org/u/vwesley)\
**Post date:** [April 23, 2026, 9:06am UTC](https://forum.mautic.org/t/scaling-mautic-how-we-achieved-multi-tenancy-single-code-multi-db/38145/1 "2026-04-23T09:06:33Z")

</div>

Hi everyone,

I wanted to share how we implemented **multi-tenancy in Mautic** using a **single codebase with multiple database instances**. The goal was to make it **highly scalable, flexible, and production-ready** for multiple clients.

This approach worked really well for us in real-world uses. It also helped us turn Mautic into a SaaS-like platform, where a single instance can serve multiple clients without things getting messy.

## High-Level Architecture

We designed the system as follows:

- One Core Database
- Multiple Tenant Databases (one per tenant)

### Core DB handles:

- Users
- Authentication
- Tenant registry
- Mapping users ↔ tenants

### Tenant DB handles:

- Contacts
- Segments
- Campaigns
- Emails
- Plugins
- Permissions
- Everything Mautic-related for that tenant

## Architecture Flowchart

 ![mermaid-drawing (1)](https://us1.discourse-cdn.com/flex020/uploads/mautic/original/2X/d/dbd3369b11416da9f2f7b1bf34342531abc4ee89.png)

The idea is simple: one instance serving many isolated databases.

- **Core Database:** Handles the Core data like user authentication, tenants data, and a mapping table (tenant\_users) that defines who has access to which tenant.

- **Tenant Databases:** Each project/tenant has their own completely isolated database.

- **Dynamic Configuration:** Instead of a single `local.php`, we store tenant-specific configs in `app/config/tenant/{tenant_id}.php`

## Authentication Flow

 ![mermaid-drawing (2)](https://us1.discourse-cdn.com/flex020/uploads/mautic/original/2X/5/5a530e8b0cc417c0ca0652a21813c1d40589986e.png)

**Step-by-step:**

1. User sends login request
2. Core DB validates credentials
3. On success:
  - Check if **tenant cookie exists**

4. Once tenant is resolved:
  - Load tenant DB

  - Validate user permissions from tenant DB

5. Login successful

## Request Lifecycle Flow

 ![mermaid-drawing (3)](https://us1.discourse-cdn.com/flex020/uploads/mautic/original/2X/a/a128fd2ba37a38208a62f398d9e8f0774a82aa06.png)

The **tenant DB connection stays consistent** throughout the request lifecycle.

## Public & API URLs

Since tracking pixels, landing pages, and API calls don’t use cookies, we updated the URL pattern: `mautic-url.com/t/{tenant_id}/{original-path}` The middleware extracts the `{tenant_id}` directly from the URL to route the data to the correct DB instantly.

## Switching Between Tenants

 ![image](https://us1.discourse-cdn.com/flex020/uploads/mautic/original/2X/2/2a47765c1ade27ba035c1b62217df95b1b4ddb1e.png)

We added a simple UX improvement

- Dropdown in top navigation
- Shows all accessible tenants
- On selection:
  - Updates tenant cookie
  - Reloads context

## Command Handling (CLI)

We extended Mautic commands with an optional parameter. `--tenant-id`

- If tenant ID is provided → runs for that tenant
- If not provided → runs for **all tenants**

### Example

```bash
php bin/console mautic:emails:send --tenant-id=1

```

This makes cron jobs super flexible.

## Installation

We modified the installation steps. During setup, you specify Core DB credentials and your first Tenant DB. You can choose to host the DB on the same server or point to a remote DB server.

 ![image](https://us1.discourse-cdn.com/flex020/uploads/mautic/original/2X/f/fac844a94d17c70f56d7fe6206ecde9302a59d80.png)

## Tenant Management

There is a dedicated Manage Tenants page. Creating a new client is a 10-second process. System creates the DB, creates the schema, and generates the config file automatically.

 ![image](https://us1.discourse-cdn.com/flex020/uploads/mautic/original/2X/1/1d73ed8e5c477495e4a93e911525627526815653.png)

Video link: [https://drive.google.com/file/d/1w3KPZZmz0J8pS1s77-y77RQn3Ti4ZCwr/view?usp=sharing](https://drive.google.com/file/d/1w3KPZZmz0J8pS1s77-y77RQn3Ti4ZCwr/view?usp=sharing)

## New Configuration Parameters

We also introduced a couple of configuration options to make things more controlled and flexible:

```php
'max_tenants_limit' => 10,
'allow_remote_db_for_tenants' => true,

```

- **max\_tenants\_limit** → This helps restrict how many tenants can be created in a single instance. Useful to avoid overloading the system or to control usage based on your setup.

- **allow\_remote\_db\_for\_tenants** → When enabled, it allows tenant databases to be hosted on remote servers.

## Why This is Highly Scalable?

1. **Database Decoupling:** You can host the application on Server A and the tenant database on Server B (with SSL support). This is crucial for clients with strict data residency requirements.

2. **Custom Domains:** Supports domain mapping. Client A can use `marketing.clientA.com` while Client B uses `mautic.clientB.com`. The middleware validates the domain against the Core DB to ensure the request hits the right data.

3. **Easy Horizontal Scaling:** Add new tenants without affecting others. No shared DB bottleneck

4. **Tenant Isolation:** Each tenant has its own email settings, its own plugins, and its own user roles. They never even know other tenants exist on the same server.

5. **Compliance Friendly:** Clients can host their own data. Supports secure connections (SSL)

6. Single Codebase Maintenance

Would love to hear more ideas or suggestions from the community on how we can make this even more robust. Always open to feedback and improvements 👍

---

<div class="post-metadata">

**Author:** ![dband](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.mautic.org/dband/32/12768_2.png) [@dband](https://forum.mautic.org/u/dband)\
**Post date:** [April 23, 2026, 3:00pm UTC](https://forum.mautic.org/t/scaling-mautic-how-we-achieved-multi-tenancy-single-code-multi-db/38145/2 "2026-04-23T15:00:48Z")

</div>

@vwesley aren’t the cronjobs the bottleneck? Could you tell us more about your setup, e.g. are you running K8?

---

<div class="post-metadata">

**Author:** ![vwesley](https://avatars.discourse-cdn.com/v4/letter/v/ebca7d/32.png) [@vwesley](https://forum.mautic.org/u/vwesley)\
**Post date:** [April 24, 2026, 6:32am UTC](https://forum.mautic.org/t/scaling-mautic-how-we-achieved-multi-tenancy-single-code-multi-db/38145/3 "2026-04-24T06:32:45Z")

</div>

@dband That’s correct.  
Have few plans to implement Redis/RabbitMQ having seperate worker for each tenant job.

At this moment, we are using docker setup. Would like to explore more about EKS or others

---

<div class="post-metadata">

**Author:** ![dband](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.mautic.org/dband/32/12768_2.png) [@dband](https://forum.mautic.org/u/dband)\
**Post date:** [April 24, 2026, 9:00am UTC](https://forum.mautic.org/t/scaling-mautic-how-we-achieved-multi-tenancy-single-code-multi-db/38145/4 "2026-04-24T09:00:38Z")

</div>

That’s the right direction. The problems you need to solve are similar to those in SaaS apps. Resource monitoring, limiting, etc. per client.

It’s a cool idea but will be a struggle to keep in sync with core changes.

---

<div class="post-metadata">

**Author:** ![mneumann](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.mautic.org/mneumann/32/2512_2.png) [@mneumann](https://forum.mautic.org/u/mneumann)\
**Post date:** [April 29, 2026, 5:40pm UTC](https://forum.mautic.org/t/scaling-mautic-how-we-achieved-multi-tenancy-single-code-multi-db/38145/5 "2026-04-29T17:40:01Z")

</div>

Maybe you could make a proposal to merge that with core, that will help a lot to resolve the upgrade path.

---

<div class="post-metadata">

**Author:** ![fianbiasa](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.mautic.org/fianbiasa/32/1249_2.png) [@fianbiasa](https://forum.mautic.org/u/fianbiasa)\
**Post date:** [August 29, 2026, 12:51pm UTC](https://forum.mautic.org/t/scaling-mautic-how-we-achieved-multi-tenancy-single-code-multi-db/38145/6 "2026-08-29T12:51:36Z")

</div>

very very **awesome** … 👏

---

<div class="post-metadata">

**Author:** ![vwesley](https://avatars.discourse-cdn.com/v4/letter/v/ebca7d/32.png) [@vwesley](https://forum.mautic.org/u/vwesley)\
**Post date:** [August 31, 2026, 6:32am UTC](https://forum.mautic.org/t/scaling-mautic-how-we-achieved-multi-tenancy-single-code-multi-db/38145/7 "2026-08-31T06:32:28Z")

</div>

@dband  
**Quick update:** We have added RabbitMQ/Redis for efficient queue and job handling.

Jobs are now processed independently for each tenant/project, so no project will depend on another project for its jobs to run.

The workers will also distribute the workload dynamically. For example, if one tenant has a large number of jobs to process while another tenant has little or no workload, the available workers will be utilised to handle the overall load.

---

<div class="post-metadata">

**Author:** ![alexzlobin](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.mautic.org/alexzlobin/32/13606_2.png) [@alexzlobin](https://forum.mautic.org/u/alexzlobin)\
**Post date:** [September 24, 2026, 4:50pm UTC](https://forum.mautic.org/t/scaling-mautic-how-we-achieved-multi-tenancy-single-code-multi-db/38145/8 "2026-09-24T16:50:59Z")

</div>

![MauticControlCenter](https://us1.discourse-cdn.com/flex020/uploads/mautic/original/2X/9/945916b7340ae6792432f36089d86fca7493b986.jpeg)

**My preciousss… She does everything! Updates, plugins, backups, migrations… everything, yes, everything! My preciousss! 😂**
