Multi-tenant mode allows Matcher to serve multiple clients with complete data isolation. Each tenant operates in its own database, message broker, and cache namespace — ensuring that one tenant’s data is never visible to another. This is essential for SaaS deployments, regulated environments, or any scenario where strict data boundaries between clients are required.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.
Overview
By default, Matcher runs in single-tenant mode: all requests share one database and one set of infrastructure connections. This is the simplest setup and works well for single-client deployments. When multi-tenant mode is enabled, each tenant receives:
- Isolated database — a dedicated PostgreSQL database provisioned and managed by the Tenant Manager service
- Isolated message broker — a dedicated RabbitMQ virtual host, plus
X-Tenant-IDheaders on every message as defense-in-depth - Isolated cache — all Redis keys are automatically prefixed with the tenant identifier
- Isolated storage — S3 objects are prefixed with the tenant identifier
tenant_id claim in the token tells Matcher which tenant the request belongs to, and the correct infrastructure connections are resolved automatically. The legacy tenantId claim is also accepted as a fallback for backward compatibility.
How to activate
Prerequisites
- The Tenant Manager service must be running and reachable from Matcher’s network. You can verify this by calling its
/healthendpoint. - Matcher must be configured with authentication enabled (
PLUGIN_AUTH_ENABLED=true), since tenant identity comes from the JWT token.
Configuration
Multi-tenant settings are configured through environment variables, just like other Matcher settings. Where you set them depends on your deployment method:- Docker Compose: add them to a
.envfile in the project root or directly indocker-compose.ymlunder theenvironmentsection - Kubernetes / Helm: add them to your Helm values file under the appropriate environment section
- Standalone: set them in your shell environment or process manager configuration
Refer to the Installation guide for details on where environment files are located in your deployment.
Required variables
Add these to your environment configuration to enable multi-tenant mode:Optional tuning
You can adjust pool sizes, timeouts, and circuit breaker behavior:Tenant isolation
Database isolation
Each tenant gets its own PostgreSQL database. When a request arrives, Matcher resolves the tenant from the JWT and connects to that tenant’s dedicated database. If no connection pool exists yet for that tenant, one is created on demand using configuration from the Tenant Manager. Connection pools are bounded byMULTI_TENANT_MAX_TENANT_POOLS and evicted when idle beyond MULTI_TENANT_IDLE_TIMEOUT_SEC.
Message broker isolation
RabbitMQ isolation uses two layers:- Virtual host per tenant — each tenant’s messages are routed through a dedicated vhost, preventing any cross-tenant message leakage
- Tenant ID headers — every published message includes an
X-Tenant-IDheader as an additional safety layer for downstream consumers
Cache isolation
All Redis keys are automatically prefixed with the tenant identifier in the formattenant:{tenantID}:{key}. This applies to idempotency checks, deduplication, rate limiting, and credential caching.
Storage isolation
Objects stored in S3-compatible storage are prefixed with{tenantID}/, ensuring each tenant’s exports and archives are separated at the storage level.
Connection pool management
Matcher maintains a pool of database connections for each active tenant. These settings control resource usage:
| Variable | Default | Description |
|---|---|---|
MULTI_TENANT_MAX_TENANT_POOLS | 100 | Maximum number of tenant pools maintained simultaneously. When the limit is reached, the least recently used pool is evicted. |
MULTI_TENANT_IDLE_TIMEOUT_SEC | 300 | How long (in seconds) an unused tenant pool stays open before being cleaned up. |
Capacity planning
Each tenant pool uses up toPOSTGRES_MAX_OPEN_CONNS connections (default: 25). With 100 tenant pools, the worst-case total is 2,500 PostgreSQL connections. Size your database’s max_connections accordingly.
Automatic health checks
Matcher periodically re-checks tenant configuration (everyMULTI_TENANT_CONNECTIONS_CHECK_INTERVAL_SEC, default 30s) to detect credential rotation or pool setting changes. Updated settings are applied without requiring a restart.
Circuit breaker
If the Tenant Manager becomes unreachable, a circuit breaker protects Matcher from cascading failures.
| Variable | Default | Description |
|---|---|---|
MULTI_TENANT_CIRCUIT_BREAKER_THRESHOLD | 5 | How many consecutive failures before the circuit breaker activates. |
MULTI_TENANT_CIRCUIT_BREAKER_TIMEOUT_SEC | 30 | How long the breaker stays active before allowing a retry. |
Tenant config caching
To reduce calls to the Tenant Manager, Matcher caches tenant configurations in memory.
| Variable | Default | Description |
|---|---|---|
MULTI_TENANT_CACHE_TTL_SEC | 120 | How long (in seconds) tenant config is cached before refreshing from the Tenant Manager. |
M2M credentials (Fetcher integration)
When multi-tenant mode is enabled and Matcher needs to call the Fetcher service, it authenticates using per-tenant machine-to-machine (M2M) credentials stored in AWS Secrets Manager.
How it works
- When Matcher calls Fetcher on behalf of a tenant, it looks up that tenant’s credentials
- Credentials are cached at two levels for performance: in-memory (30 seconds) and Redis (configurable TTL)
- If Fetcher returns a
401 Unauthorized, both caches are automatically cleared and fresh credentials are fetched
Configuration
Add these to your environment configuration if Matcher needs to call Fetcher in multi-tenant mode:The service’s IAM role needs
secretsmanager:GetSecretValue permission for the path tenants/{env}/{tenantOrgID}/matcher/m2m/fetcher/credentials.All environment variables
Multi-tenant infrastructure
| Variable | Type | Default | Required | Description |
|---|---|---|---|---|
MULTI_TENANT_ENABLED | bool | false | No | Master switch for multi-tenant mode. |
MULTI_TENANT_URL | string | — | Yes (when enabled) | Base URL of the Tenant Manager service. |
MULTI_TENANT_SERVICE_API_KEY | string | — | Yes (when enabled) | API key for authenticating with the Tenant Manager. |
MULTI_TENANT_ENVIRONMENT | string | — | No | Environment label for tenant resolution. |
MULTI_TENANT_MAX_TENANT_POOLS | int | 100 | No | Maximum concurrent tenant connection pools. |
MULTI_TENANT_IDLE_TIMEOUT_SEC | int | 300 | No | Seconds before an idle tenant pool is evicted. |
MULTI_TENANT_TIMEOUT | int | 30 | No | HTTP timeout (seconds) for Tenant Manager API calls. |
MULTI_TENANT_CIRCUIT_BREAKER_THRESHOLD | int | 5 | No | Consecutive failures before circuit breaker activates. |
MULTI_TENANT_CIRCUIT_BREAKER_TIMEOUT_SEC | int | 30 | No | Seconds the circuit breaker stays active. |
MULTI_TENANT_CACHE_TTL_SEC | int | 120 | No | Cache TTL (seconds) for tenant configurations. |
MULTI_TENANT_CONNECTIONS_CHECK_INTERVAL_SEC | int | 30 | No | Interval (seconds) for connection pool health checks. |
MULTI_TENANT_REDIS_HOST | string | — | No | Redis host for event-driven tenant discovery. |
MULTI_TENANT_REDIS_PORT | string | 6379 | No | Redis port for tenant discovery. |
MULTI_TENANT_REDIS_PASSWORD | string | — | No | Redis password for tenant discovery. |
MULTI_TENANT_REDIS_TLS | bool | false | No | Enable TLS for tenant discovery Redis. |
Default tenant
| Variable | Type | Default | Description |
|---|---|---|---|
DEFAULT_TENANT_ID | string | 11111111-1111-1111-1111-111111111111 | UUID of the default (fallback) tenant. Used in single-tenant mode. |
DEFAULT_TENANT_SLUG | string | default | Slug of the default tenant. |
M2M credentials (Fetcher)
| Variable | Type | Default | Required | Description |
|---|---|---|---|---|
M2M_TARGET_SERVICE | string | fetcher | No | Target service name for credential lookup. |
M2M_CREDENTIAL_CACHE_TTL_SEC | int | 300 | No | Redis cache TTL (seconds) for M2M credentials. |
AWS_REGION | string | — | Yes (if M2M) | AWS region for Secrets Manager. |
Verifying multi-tenant mode
After activating multi-tenant mode, verify that everything is working:
- Check startup logs. Look for messages confirming that multi-tenant infrastructure was initialized successfully.
-
Test with a tenant JWT. Send an API request (for example, list contexts) using a JWT that contains a
tenant_idclaim. The request should succeed and return data for that specific tenant. - Verify isolation. Make the same API call with JWTs for two different tenants. Confirm that data created under one tenant is not visible to the other.
-
Check metrics (if telemetry is enabled). The
tenant_connections_totalmetric should increment as new tenant pools are created. - Verify M2M credentials (if using Fetcher). Check logs for successful credential retrieval when Matcher calls Fetcher for a tenant.
Deactivating multi-tenant mode
To return to single-tenant mode:
- Set
MULTI_TENANT_ENABLED=falsein your environment configuration (or remove the variable entirely). - Restart the Matcher service.
Deployment considerations
Redis key migration
Redis key migration
When switching from single-tenant to multi-tenant mode, Redis keys change format. Old-format keys are treated as cache misses until their TTL expires. This is self-healing and typically resolves within 1–5 minutes.
S3 object migration
S3 object migration
Existing objects created before multi-tenant activation remain at their original paths. New objects get the tenant prefix automatically. If historical data must be accessible per tenant, a one-time migration script may be needed.
Connection pool sizing
Connection pool sizing
Plan your PostgreSQL
max_connections based on the maximum number of tenant pools multiplied by connections per pool. Use MULTI_TENANT_IDLE_TIMEOUT_SEC to reclaim pools for inactive tenants.Circuit breaker during Tenant Manager outages
Circuit breaker during Tenant Manager outages
While the circuit breaker is active, new-tenant requests fail fast but existing tenant pools continue working. Plan for Tenant Manager high availability in production.
Next steps
Runtime configuration
Change Matcher settings at runtime without restarts.
Installation guide
Set up Matcher from scratch.
Security
Authentication, authorization, and data protection.
Discovery (Fetcher)
Automatic source discovery through Fetcher.

