Course contentsShow
← Databases & SQL
Lesson 964 of 1,9538. PostgreSQL InternalsFree lesson

System Resource Limits (Cgroups/Ulimits)

You will isolate database resource usage using operating system level constraints.

In this lesson, you will learn how to enforce "sandbox" boundaries on your PostgreSQL processes to ensure the database doesn't starve the rest of your server.

While PostgreSQL has internal settings like work_mem to manage memory per operation, these are "soft" constraints that depend on the number of concurrent connections. If a sudden spike in traffic occurs, the OS might experience memory exhaustion or CPU starvation. To prevent this, we look to the operating system: ulimits and cgroups.

Ulimits: The "Personal" Hard Cap

ulimits are per-user or per-process constraints. They are ideal for preventing a single database user from opening too many files or consuming excessive stack memory. You configure these in /etc/security/limits.conf. For example, to ensure your postgres user never accidentally crashes the system by opening too many file descriptors, you might set:

postgres soft nofile 65536
postgres hard nofile 65536

This prevents the "too many open files" error from cascading into an OS-wide failure, forcing the database to reject new connections rather than crashing the kernel.

Cgroups: The "Hard" Container

While ulimits control individual process behavior, Control Groups (cgroups) act as a hard fence around a collection of processes. Cgroups are how Linux manages resource allocation at the kernel level. By placing the PostgreSQL service within a specific cgroup, you can define "hard" limits on CPU cycles and total memory usage.

If you are running PostgreSQL on Linux, you can define a systemd service file (or a direct cgroup configuration) to restrict memory:

[Service]
MemoryMax=16G
CPUQuota=400%

In this setup, even if a runaway query attempts to allocate 30GB of RAM due to a poor execution plan, the kernel will step in. Instead of triggering the "OOM Killer" (which might randomly kill your database process), the kernel will restrict the cgroup, forcing the query to error out gracefully or preventing the system from locking up.

By combining ulimits for process-specific safety and cgroups for total resource allocation, you transform your database from a "best-effort" application into a predictable, bounded system participant.

Key Takeaway: Use ulimits to control individual process resource consumption and cgroups to set firm physical boundaries on total database memory and CPU usage to ensure system-wide stability.