> ## Documentation Index
> Fetch the complete documentation index at: https://docs.lerian.studio/llms.txt
> Use this file to discover all available pages before exploring further.

# Multi-tenancy

> How Lerian isolates data between tenants in shared deployments.

Multi-tenancy allows a single deployment to serve multiple independent customers — called **tenants** — with complete data isolation between them. Each tenant operates as if they had their own dedicated environment, even though the underlying infrastructure is shared.

In Lerian, multi-tenancy is available in **SaaS** (always active) and **BYOC Multi-Tenant** deployments.

### Products that support multi-tenancy

The same JWT-based tenant model applies across the platform. Currently supported:

| Product                  | Multi-tenant support | Notes                                                                                                                  |
| ------------------------ | -------------------- | ---------------------------------------------------------------------------------------------------------------------- |
| **Midaz** (Ledger + CRM) | ✅ Yes                | Organizations, ledgers, accounts, transactions, and balances are scoped to the tenant.                                 |
| **Tracer**               | ✅ Yes                | Rules, limits, validations, and audit events are scoped to the tenant. Each tenant has its own rule and limit catalog. |
| **Reporter**             | ✅ Yes                | Reports run only over the calling tenant's data.                                                                       |

Integrating any of these products is identical from the API perspective — the JWT carries the `tenantId` claim and the service resolves the tenant automatically.

## How it works

***

Tenant isolation is enforced at the application layer through your authentication token.

1. You authenticate via [Access Manager](/en/platform/access-manager/access-manager) and receive a JWT.
2. That token includes a `tenantId` claim that identifies your tenant.
3. On every API request, the platform resolves your tenant from the token automatically.
4. All operations — creating organizations, querying ledgers, posting transactions — are scoped to your tenant.

You never pass a tenant identifier in headers or request bodies. The token handles it.

<Note>
  Multi-tenancy is transparent at the API level. Your integration code is the same whether you're running single-tenant or multi-tenant — the only difference is that multi-tenant deployments require authentication on every request.
</Note>

## How tenant scoping looks in each product

***

The `tenantId` from the JWT scopes every resource the calling user can see or create. The resource model differs per product:

### Midaz

A tenant is **not** the same as an [organization](/en/midaz/organizations). A single tenant can create and manage multiple organizations — for example, to represent subsidiaries, regional branches, or different business units.

```
Tenant (resolved from JWT)
├── Organization A
│   ├── Ledger 1
│   └── Ledger 2
├── Organization B
│   └── Ledger 3
```

When you list organizations, you only see the ones that belong to your tenant. The same applies to every Midaz resource — ledgers, accounts, transactions, and balances are all scoped to your tenant automatically.

### Tracer

Tracer scopes its catalog directly under the tenant — there is no organization layer.

```
Tenant (resolved from JWT)
├── Rules
├── Limits
├── Validations
└── Audit events
```

When you list rules or limits, you only see entries created by your tenant. Validations execute against the tenant's own rules and limits, never against another tenant's. Audit events are likewise tenant-scoped — even hash-chain verification runs over the calling tenant's chain only.

### Other products

Reporter and the rest of the platform follow the same pattern: the tenant is the outermost scope, and the JWT is the only source of truth for which tenant the caller belongs to.

## Data isolation

***

Tenant data is isolated at the database level. Each tenant operates on a separate database, meaning:

* Data from different tenants is never stored together.
* Queries from one tenant cannot reach another tenant's data.
* Even if two tenants create identical organization structures, their data remains completely separate.

This isolation is enforced by middleware that routes each request to the correct database based on the `tenantId` claim in your JWT. There is no way to bypass this through the API.

<Note>
  BYOC operators can choose between database-level or schema-level isolation depending on their infrastructure requirements.
</Note>

## What this means for you

***

### If you are a SaaS customer

Nothing changes in how you use the API. Authenticate, get your token, and make requests. The platform handles isolation transparently. You don't need to manage tenant identifiers or worry about data leaking between customers.

### If you are a BYOC operator running multi-tenant

You configure which tenants exist and how their databases are provisioned. Your clients authenticate through Access Manager and receive scoped tokens. The platform routes each request to the correct tenant database automatically.

### If you are running single-tenant (BYOC or local development)

Multi-tenancy is disabled by default. Your existing setup continues to work without changes. No JWT tenant claim is required, and authentication can be optional depending on your configuration.

## Configuration (BYOC operators)

***

Multi-tenancy is disabled by default in every product. To enable it, set `MULTI_TENANT_ENABLED=true` in the environment of each product you want to run multi-tenant (Midaz, Tracer, Reporter). Once enabled, the product requires a running [Tenant Manager](https://github.com/LerianStudio/tenant-manager) service and authentication on every request.

### Core settings

These variables apply to every multi-tenant-capable product (Midaz Ledger, Midaz CRM, Tracer, Reporter):

| Variable                                      | Description                                                                                                  | Default |
| :-------------------------------------------- | :----------------------------------------------------------------------------------------------------------- | :------ |
| `MULTI_TENANT_ENABLED`                        | Enable multi-tenant mode. When `false`, the platform runs in single-tenant mode.                             | `false` |
| `MULTI_TENANT_URL`                            | URL of the Tenant Manager service. Required when multi-tenant is enabled.                                    | —       |
| `MULTI_TENANT_SERVICE_API_KEY`                | API key for authenticating with the Tenant Manager. Required when multi-tenant is enabled.                   | —       |
| `MULTI_TENANT_CONNECTIONS_CHECK_INTERVAL_SEC` | How often (seconds) the platform revalidates tenant configurations against the Tenant Manager.               | —       |
| `MULTI_TENANT_CACHE_TTL_SEC`                  | How long (seconds) tenant configuration is cached locally before re-fetching. Set to `0` to disable caching. | `120`   |

### Tenant Manager circuit breaker

Protects against Tenant Manager outages by failing fast when the service is unavailable:

| Variable                                   | Description                                                | Default |
| :----------------------------------------- | :--------------------------------------------------------- | :------ |
| `MULTI_TENANT_CIRCUIT_BREAKER_THRESHOLD`   | Consecutive failures before the circuit opens.             | `5`     |
| `MULTI_TENANT_CIRCUIT_BREAKER_TIMEOUT_SEC` | How long (seconds) the circuit stays open before retrying. | `30`    |

### Redis cache

Multi-tenant mode uses Redis to cache tenant configurations across instances:

| Variable                      | Description                          | Default |
| :---------------------------- | :----------------------------------- | :------ |
| `MULTI_TENANT_REDIS_HOST`     | Redis server hostname.               | —       |
| `MULTI_TENANT_REDIS_PORT`     | Redis server port.                   | `6379`  |
| `MULTI_TENANT_REDIS_PASSWORD` | Redis authentication password.       | —       |
| `MULTI_TENANT_REDIS_TLS`      | Enable TLS for the Redis connection. | `false` |

### CRM-specific settings

These variables are only available in the CRM component and control connection pool behavior for multi-tenant database connections:

| Variable                        | Description                                                                     | Default |
| :------------------------------ | :------------------------------------------------------------------------------ | :------ |
| `MULTI_TENANT_TIMEOUT`          | HTTP client timeout (seconds) for requests to the Tenant Manager.               | `30`    |
| `MULTI_TENANT_MAX_TENANT_POOLS` | Maximum number of concurrent database connection pools (one per active tenant). | `100`   |
| `MULTI_TENANT_IDLE_TIMEOUT_SEC` | How long (seconds) before an idle tenant connection pool is evicted.            | `300`   |

<Tip>
  For most deployments, the defaults work well. Tune `CACHE_TTL_SEC` and `CONNECTIONS_CHECK_INTERVAL_SEC` based on how frequently you add or modify tenants — lower values mean faster propagation of tenant changes, higher values reduce load on the Tenant Manager.
</Tip>

<Note>
  `MULTI_TENANT_ENABLED=true` requires `PLUGIN_AUTH_ENABLED=true`. Authentication must be active for tenant isolation to work — the platform resolves tenants from the JWT claim.
</Note>

## Related pages

***

<CardGroup>
  <Card title="Deployment models" icon="cloud" href="/en/deployment-models" cta="Compare SaaS and BYOC">
    Understand the differences between SaaS, BYOC Single-Tenant, and BYOC Multi-Tenant.
  </Card>

  <Card title="Security" icon="shield-halved" href="/en/midaz/security" cta="Read about security">
    Learn about tenant isolation guarantees and the shared responsibility model.
  </Card>

  <Card title="Access Manager" icon="key" href="/en/platform/access-manager/access-manager" cta="Learn about authentication">
    Understand how authentication and JWT-based tenant resolution work.
  </Card>

  <Card title="Organizations" icon="building" href="/en/midaz/organizations" cta="Manage organizations">
    Learn how organizations are structured within a tenant.
  </Card>
</CardGroup>
