Skip to main content
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.

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 multi-tenancy platform service
  • Isolated message broker — a dedicated RabbitMQ virtual host, plus X-Tenant-ID headers 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 identity is determined from the JWT token in each API request. The 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 multi-tenancy platform service must be running and reachable from Matcher’s network before enabling multi-tenant mode.
  • 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 .env file in the project root or directly in docker-compose.yml under the environment section
  • 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:
After updating the configuration, restart the Matcher service. On startup, you should see log messages confirming that multi-tenant infrastructure was initialized.

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 multi-tenancy platform service. Connection pools are bounded by MULTI_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-ID header as an additional safety layer for downstream consumers
No manual vhost creation is needed. The multi-tenancy platform service provisions vhosts automatically.

Cache isolation

All Redis keys are automatically prefixed with the tenant identifier in the format tenant:{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:

Capacity planning

Each tenant pool uses up to POSTGRES_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 (every MULTI_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 multi-tenancy platform service becomes unreachable, a circuit breaker protects Matcher from cascading failures. While the circuit breaker is active, requests for new tenants will fail fast. However, existing tenant connections continue working normally — only new tenant onboarding is affected.

Tenant config caching


To reduce calls to the multi-tenancy platform service, Matcher caches tenant configurations in memory. On the first request for a tenant, Matcher fetches the configuration from the multi-tenancy platform service API and caches it. Subsequent requests for the same tenant are served from cache until the TTL expires.

All environment variables


Multi-tenant infrastructure

bool
default:"false"
Master switch for multi-tenant mode.
string
Required when multi-tenant mode is enabled. Base URL of the multi-tenancy platform service.
string
Required when multi-tenant mode is enabled. API key for authenticating with the multi-tenancy service.
string
Environment label for tenant resolution.
int
default:"100"
Maximum concurrent tenant connection pools.
int
default:"300"
Seconds before an idle tenant pool is evicted.
int
default:"30"
HTTP timeout (seconds) for multi-tenancy service calls.
int
default:"5"
Consecutive failures before circuit breaker activates.
int
default:"30"
Seconds the circuit breaker stays active.
int
default:"120"
Cache TTL (seconds) for tenant configurations.
int
default:"30"
Interval (seconds) for connection pool health checks.
string
Redis host for event-driven tenant discovery.
string
default:"6379"
Redis port for tenant discovery.
string
Redis password for tenant discovery.
bool
default:"false"
Enable TLS for tenant discovery Redis.

Default tenant

string
default:"11111111-1111-1111-1111-111111111111"
UUID of the default (fallback) tenant. Used in single-tenant mode.
string
default:"default"
Slug of the default tenant.

Verifying multi-tenant mode


After activating multi-tenant mode, verify that everything is working:
  1. Check startup logs. Look for messages confirming that multi-tenant infrastructure was initialized successfully.
  2. Test with a tenant JWT. Send an API request (for example, list contexts) using a JWT that contains a tenant_id claim. The request should succeed and return data for that specific tenant.
  3. 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.
  4. Check metrics (if telemetry is enabled). The tenant_connections_total metric should increment as new tenant pools are created.

Deactivating multi-tenant mode


To return to single-tenant mode:
  1. Set MULTI_TENANT_ENABLED=false in your environment configuration (or remove the variable entirely).
  2. Restart the Matcher service.
The service will operate with a single shared database and the default tenant identity will apply to all requests.

Deployment considerations


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.
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.
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.
While the circuit breaker is active, new-tenant requests fail fast but existing tenant pools continue working. Plan for multi-tenancy platform service 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.