All Products
Search
Document Center

PolarDB:Multi-tenancy

Last Updated:Mar 28, 2026

When multiple workloads share a single PolarDB for PostgreSQL (Compatible with Oracle) cluster, one workload can consume disproportionate CPU or memory and starve others. Multi-tenancy lets you define resource limits at the tenant level — grouping databases, users, or individual processes under a shared CPU and memory cap — so that resource-intensive workloads cannot degrade the rest of the cluster.

Supported versions

Oracle Syntax Compatibility 2.0, minor engine version 2.0.14.12.24.0 or later.

To check your minor engine version, run SHOW polardb_version; or view the version in the console. If your cluster does not meet the version requirement, upgrade the minor engine version.

How it works

Tenant hierarchy

A tenant is a logical resource boundary within a cluster — sitting above users and databases, but below the cluster itself. Multiple users and databases can belong to a single tenant.

There are two tenant types:

TypeDescription
System tenantA special administrative tenant. Each cluster has exactly one system tenant. It has priority access to cluster resources and can use resources from regular tenants. A user in the system tenant with cluster access permissions can access resources across all tenants.
Regular tenantResources are fully isolated from other tenants. Regular tenants must be created from within the system tenant context.

Resource configuration

A resource configuration defines the CPU and memory limits applied to a tenant. You create a resource configuration separately, then attach it to a tenant. Detaching or deleting the tenant does not delete the resource configuration.

Resource tracking dimensions

Every session in PolarDB for PostgreSQL corresponds to a single process. Each process belongs to exactly one tenant, which prevents double-counting. The system maps processes to tenants along three dimensions:

DimensionScope
ProcessA single connection process initiated by a user, including any parallel query processes it spawns. System auxiliary processes are excluded.
UserAll connection processes from the same user, including parallel query processes. System auxiliary processes are excluded.
DatabaseAll connection processes accessing the same database, including parallel query processes. System auxiliary processes are excluded.

Parallel query child processes automatically join the tenant of the session that issued the query, and are removed from the tenant when the query finishes.

System processes have no resource limits by default.

Resource limit enforcement

CPU and memory use different enforcement mechanisms:

ResourceEnforcementWhat the user sees when the limit is exceeded
CPUThrottling — the cluster slows down processes to stay within the limit.Queries run slower.
MemoryEviction — sessions are terminated to release memory. Swap is disabled, so memory is a hard constraint.Session is aborted with a memory over-limit error.

Parameters

Parameters that require a restart take effect only after the cluster restarts. Parameters that require a RELOAD take effect after running SELECT pg_reload_conf();.

ParameterDescriptionRangeDefaultWhen it takes effect
polar_max_tenantsMaximum number of tenants0–6553632After restart
polar_resource_manager.enable_resource_managerEnables the Resource Manager process for memory limiting and out-of-memory (OOM) preventionon/offonAfter restart
polar_resource_manager.database_nameDatabase that stores tenant metadatapolardb_adminAfter restart
polar_resource_manager.stat_intervalData collection interval10–10000 ms500 msAfter RELOAD
polar_resource_manager.total_mem_request_rateActive eviction threshold50%–100%80%After RELOAD
polar_resource_manager.total_mem_limit_rateForced eviction threshold50%–100%95%After RELOAD
polar_resource_manager.total_mem_limit_remain_sizeReserved memory131072–INT_MAX KB256000 KBAfter RELOAD
polar_resource_manager.enable_logEnables log recordsON/OFFONAfter RELOAD

Set up multi-tenancy

Before you begin

  • A PolarDB for PostgreSQL (Compatible with Oracle) cluster running Oracle Syntax Compatibility 2.0, minor engine version 2.0.14.12.24.0 or later

Step 1: Install the extension

Install the polar_resource_manager extension in the database specified by polar_resource_manager.database_name (default: polardb_admin):

CREATE EXTENSION polar_resource_manager;
Important

If you change the value of polar_resource_manager.database_name, all existing multi-tenancy configuration becomes invalid.

Step 2: Create a resource configuration

SELECT polar_resource_manager.polar_create_resource_config('resource_config_name');

resource_config_name follows database object naming rules. Names longer than 64 bytes are truncated automatically.

Step 3: Set resource limits

Set the CPU limit (in cores) and the memory limit (in bytes) on the resource configuration:

-- Set CPU limit: 0.3 = 30% of one CPU core; 2 = two full CPU cores
SELECT polar_resource_manager.polar_alter_resource_config('resource_config_name', 'cpu_rate_limit', 2);

-- Set memory limit in bytes
SELECT polar_resource_manager.polar_alter_resource_config('resource_config_name', 'mem_limit', value);

cpu_rate_limit is measured in cores (float). A value of 0.3 limits usage to 30% of one core; a value of 2 allows up to two full cores. The sum of cpu_rate_limit values across all tenants can exceed the cluster's total physical CPU capacity — the system throttles processes when individual limits are reached.

mem_limit is in bytes. For enforcement behavior when a tenant exceeds its memory limit, see Memory resource management.

Step 4: Create a tenant

A resource configuration must exist before you create a tenant.

SELECT polar_resource_manager.polar_create_tenant('tenant_name', 'resource_config_name');

tenant_name follows database object naming rules. Names longer than 64 bytes are truncated automatically.

To modify an existing tenant:

-- Rename the tenant
SELECT polar_resource_manager.polar_alter_tenant('tenant_name', 'name', 'new_tenant_name');

-- Switch the resource configuration
SELECT polar_resource_manager.polar_alter_tenant('tenant_name', 'resource_config', 'new_resource_config_name');

To delete a tenant (this does not delete the attached resource configuration):

SELECT polar_resource_manager.polar_drop_tenant('tenant_name');

To delete a resource configuration:

SELECT polar_resource_manager.polar_drop_resource_config('resource_config_name');

Step 5: Assign databases, users, or processes

Assign at least one database, user, or process to the tenant so that sessions are tracked against its resource limits.

Assign a database

A database can belong to only one tenant. Assigning it to another tenant fails.

SELECT polar_resource_manager.polar_tenant_add_database('tenant_name', 'database_name');

To view current database-to-tenant assignments:

SELECT dbsname, tenantname FROM polar_resource_manager.polar_tenants_dbs;

Assign a user

A user can belong to only one tenant. Assigning them to another tenant fails.

SELECT polar_resource_manager.polar_tenant_add_user('tenant_name', 'user_name');

To view current user-to-tenant assignments:

SELECT username, tenantname FROM polar_resource_manager.polar_tenants_users;

Assign a process

A process can belong to only one tenant. If you assign a process to multiple tenants, only the last assignment takes effect.

SELECT polar_resource_manager.polar_tenant_add_process('tenant_name', pid);

Step 6: View resource usage

Query the polar_all_resource_configs_detail view for a snapshot of all tenants' resource usage:

SELECT * FROM polar_resource_manager.polar_all_resource_configs_detail;
ColumnTypeDescription
tenantnameNAMETenant name
resource_config_nameNAMEResource configuration name
num_processesINTEGERTotal number of processes
num_idle_processesINTEGERNumber of idle processes
num_active_processesINTEGERNumber of active processes
cpu_rate_limitDOUBLE PRECISIONCPU limit for the tenant (in cores)
per_process_cpu_rate_limitDOUBLE PRECISIONCPU limit per process
mem_limitDOUBLE PRECISIONMemory limit (in bytes)
mem_usageDOUBLE PRECISIONCurrent memory usage
idle_processes_mem_usageDOUBLE PRECISIONMemory used by idle processes
active_processes_mem_usageDOUBLE PRECISIONMemory used by active processes
cpu_usage_rateDOUBLE PRECISIONCurrent CPU usage rate

CPU resource management

When a tenant's CPU usage exceeds cpu_rate_limit, the cluster throttles the corresponding processes to enforce the limit.

cpu_rate_limit is measured in CPU cores (float). The sum of cpu_rate_limit values across all tenants can exceed the cluster's physical CPU capacity — this is intentional, since not all tenants are active simultaneously.

When a parallel query is running, its backend child processes join the tenant of the initiating session. When the query finishes, those child processes are removed from the tenant.

Memory resource management

Because swap is disabled, memory is a hard resource. Instead of throttling, PolarDB for PostgreSQL handles memory over-limits through tenant-level eviction — similar to OS-level out-of-memory (OOM) handling, but scoped to individual tenants rather than the entire database.

When memory usage is high, two eviction policies apply:

Active eviction (threshold: total_mem_request_rate, default 80%)

When total cluster memory usage exceeds 80%, the system checks each tenant. If a tenant's memory usage exceeds its mem_limit, the system terminates sessions in that tenant to bring usage down. This continues until total memory falls below the threshold.

Forced eviction (threshold: total_mem_limit_rate, default 95%)

When total cluster memory exceeds 95%, the system traverses all processes and terminates sessions regardless of individual tenant limits. This is a last-resort measure to prevent a cluster-wide OOM condition.

In both cases, the user receives a memory over-limit error. The eviction is triggered by sending a SIGUSR2 signal to the session process.

Parallel queries: If a parallel query's backend process exceeds the memory limit, the corresponding user session is aborted — not just the backend process.

System processes: System background processes belong to the system tenant and are not subject to active eviction.