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-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 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
.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 multi-tenancy platform service. 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:
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 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:
- 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.
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 multi-tenancy service outages
Circuit breaker during multi-tenancy service outages
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.

