Resource Manager is a background daemon in PolarDB for PostgreSQL that monitors cluster memory usage and terminates the most memory-intensive processes before the operating system is forced to intervene. Without this protection, unconstrained memory growth can trigger the kernel's out-of-memory (OOM) killer, causing unexpected process exits, cluster restarts, or full cluster unavailability.
Resource Manager is designed to limit memory, CPU, and I/O resources. Currently, only memory limits are enforced.
Applicability
The following PolarDB for PostgreSQL versions support Resource Manager:
| Version | Minimum minor engine version |
|---|---|
| PostgreSQL 18 | 2.0.18.0.1.0 |
| PostgreSQL 17 | 2.0.17.2.1.0 |
| PostgreSQL 16 | 2.0.16.3.1.1 |
| PostgreSQL 15 | 2.0.15.7.2.0 |
| PostgreSQL 14 | 2.0.14.5.1.0 |
| PostgreSQL 11 | 2.0.11.2.1.0 |
To check your current minor engine version, run SHOW polardb_version; or check the minor engine version in the console. If your version does not meet the minimum requirement, upgrade the minor engine version.
Memory architecture
A PolarDB for PostgreSQL cluster divides its memory into three parts:
-
Shared memory — fixed allocation shared across all processes
-
Dynamic shared memory — allocated on demand as workload grows
-
Private memory — per-process memory, managed by MemoryContext
Private memory has two sub-categories:
-
Work computation area memory — memory consumed during query execution and normal service operations
-
Cache memory — memory used by database processes to cache internal metadata; affects performance but not stability
Dynamic shared memory and private memory are dynamically allocated, so their usage fluctuates with workload. When both grow simultaneously, total cluster memory consumption can breach operating system limits. At that point, the kernel intervenes forcibly—terminating processes or restarting the cluster.
Resource Manager addresses this by acting earlier: it monitors memory continuously and terminates the highest consumers before the kernel takes over.
How it works
Resource Manager runs as a daemon on the primary (RW), read-only (RO), and standby nodes. It relies on cgroups to read memory usage data; if cgroups are not available, memory limits cannot be applied.
At each check interval, Resource Manager reads the cluster's memory usage from cgroups. When usage crosses either of the following thresholds, it reads the kernel's memory accounting for user processes, sorts them by memory consumption, and sends a SIGTERM or SIGINT signal to the largest consumers first:
-
Usage rate threshold — cluster memory usage exceeds
polar_resource_manager.total_mem_limit_rate(default: 95%) -
Available memory threshold — free cluster memory drops below
polar_resource_manager.total_mem_limit_remain_size(default: 262144 KB)
Either condition alone is sufficient to trigger enforcement.
Parameters
| Parameter | Description | Default | Range / Valid values |
|---|---|---|---|
polar_resource_manager.enable_resource_manager |
Enables or disables Resource Manager. | on |
on, off |
polar_resource_manager.stat_interva |
Interval between resource usage checks. Unit: milliseconds. | 500 |
10–10000 |
polar_resource_manager.total_mem_limit_rate |
Memory usage percentage that triggers enforcement. When cluster memory usage exceeds this value, Resource Manager begins terminating processes. | 95 |
Percentage |
polar_resource_manager.total_mem_limit_remain_size |
Minimum free memory threshold. When available cluster memory drops below this value, Resource Manager begins terminating processes. Unit: KB. | 262144 |
0 to MAX_KILOBYTES |
polar_resource_manager.mem_release_policy |
Policy that determines which processes to terminate. | default |
See below |
mem_release_policy values
| Value | Behavior |
|---|---|
none |
No action taken. |
default |
Terminates idle processes first, then active processes. |
cancel_query |
Cancels active queries. |
terminate_idle_backend |
Terminates idle backends. |
terminate_any_backend |
Terminates all backends. |
terminate_random_backend |
Terminates a randomly selected backend. |
Log output
When Resource Manager terminates a session, it writes two log entries: one from the daemon recording the target process and memory released, and one from the terminated session.
2022-11-28 14:07:56.929 UTC [18179] LOG: [polar_resource_manager] terminate process 13461 release memory 65434123 bytes
2022-11-28 14:08:17.143 UTC [35472] FATAL: terminating connection due to out of memory
2022-11-28 14:08:17.143 UTC [35472] BACKTRACE:
postgres: primary: postgres postgres [local] idle(ProcessInterrupts+0x34c) [0xae5fda]
postgres: primary: postgres postgres [local] idle(ProcessClientReadInterrupt+0x3a) [0xae1ad6]
postgres: primary: postgres postgres [local] idle(secure_read+0x209) [0x8c9070]
postgres: primary: postgres postgres [local] idle() [0x8d4565]
postgres: primary: postgres postgres [local] idle(pq_getbyte+0x30) [0x8d4613]
postgres: primary: postgres postgres [local] idle() [0xae1861]
postgres: primary: postgres postgres [local] idle() [0xae1a83]
postgres: primary: postgres postgres [local] idle(PostgresMain+0x8df) [0xae7949]
postgres: primary: postgres postgres [local] idle() [0x9f4c4c]
postgres: primary: postgres postgres [local] idle() [0x9f440c]
postgres: primary: postgres postgres [local] idle() [0x9ef963]
postgres: primary: postgres postgres [local] idle(PostmasterMain+0x1321) [0x9ef18a]
postgres: primary: postgres postgres [local] idle() [0x8dc1f6]
/lib64/libc.so.6(__libc_start_main+0xf5) [0x7f888afff445]
postgres: primary: postgres postgres [local] idle() [0x49d209]
Search logs for [polar_resource_manager] to identify all termination events and the memory recovered.
If process terminations are frequent, consider lowering workload concurrency, increasing the cluster's memory allocation, or raising the total_mem_limit_rate and total_mem_limit_remain_size thresholds to give workloads more headroom before enforcement begins.