StormaticsStormatics

Configuring Linux Huge Pages for PostgreSQL

Huge pages are a Linux kernel feature that allocates larger memory pages (typically 2 MB or 1 GB instead of the normal 4 KB). PostgreSQL’s shared buffer pool and dynamic shared memory segments are often tens of gigabytes, and using huge pages reduces the number of pages the processor must manage. Fewer page‑table entries mean fewer translation‑lookaside‑buffer (TLB) misses and fewer page table walks, which reduces CPU overhead and improves query throughput and parallel query performance. The PostgreSQL documentation notes that huge pages “reduce overhead … resulting in smaller page tables and less CPU time spent on memory management”[1].

This blog explains why huge pages matter and how to configure them correctly on modern PostgreSQL releases (v15–v18) running on Linux. It also covers special considerations for Kubernetes, cloud services (Amazon RDS/Aurora and Azure Database for PostgreSQL), and Windows, and emphasises disabling Transparent Huge Pages (THP).

1.  When to use huge pages and why they matter

  • Performance benefit: With large shared buffers, regular 4 KB pages cause many TLB misses. Huge pages group memory into 2 MB or 1 GB chunks, so the CPU spends less time managing memory and more on executing queries. The official docs highlight that huge pages reduce CPU overhead[1], and pganalyze notes that enabling huge pages on a dedicated PostgreSQL server can yield measurable performance improvements when shared buffers are tens of gigabytes[2].
  • Dedicated servers: Because huge pages reserve physical memory, they are best on dedicated database servers. Over‑allocating huge pages on multi‑purpose servers can starve the operating system or other services[3].
  • Use huge_pages=on for clarity: PostgreSQL’s huge_pages parameter accepts off, try (default) or on. When set to on, PostgreSQL will refuse to start if sufficient huge pages are not available; this surfaces mis‑configurations immediately[4]. The docs encourage enabling huge pages and warn that Transparent Huge Pages (THP) often degrade database performance[1] (see §4).

2.  Calculating how many huge pages are required

2.1.  PostgreSQL 15+ – use the built‑in calculator

PostgreSQL 15 introduced the shared_memory_size_in_huge_pages parameter, which reports the number of huge pages needed to hold the server’s shared memory. You can query it without starting a server:

# For 20 GiB shared buffers and 2 GiB dynamic shared memory
postgres --shared-buffers=20GB \
--min-dynamic-shared-memory=2GB \
-C shared_memory_size_in_huge_pages

This command outputs the exact number of 2 MB huge pages required (for example, ~11,499 pages for 20 GiB of buffers plus 2 GiB dynamic shared memory[3]). You can also inspect dynamic shared memory with -C dynamic_shared_memory_type or allocate a specific size via min_dynamic_shared_memory to ensure parallel workers also use huge pages[3].

2.2.  Pre‑15 releases – compute manually

For PostgreSQL 14 and earlier, compute the required huge‑page count manually:

  1. Find out the size of huge pages on the Linux system you want to run on (typically 2MB). 
  2. Divide the shared_buffers allocation (in MBs) by 2 (the size of huge pages)
  3. Add 5% as buffer, just to ensure that PostgreSQL will always have the number of huge pages required 
  4. The resultant number is the number of huge pages you should allocate. 

2.3.  1 GB huge pages

Most deployments use 2 MB pages, but some CPUs support 1 GB pages. You can request them by setting huge_page_size = 1GB in postgresql.conf[6] and allocating them via /sys/kernel/mm/hugepages/hugepages-1048576kB/nr_hugepages. Large pages reduce TLB pressure further, but memory fragmentation makes them harder to allocate; rebooting is often required[6].

3.  Allocating huge pages at the operating system level

Once you know the number of pages required, pre‑allocate them in the kernel. The following steps apply to most Linux distributions (RHEL, Ubuntu, Debian, SUSE, etc.):

1. Reserve huge pages via sysctl:

# Example: allocate 11,500 two‑megabyte pages
sysctl -w vm.nr_hugepages=11500
# To persist across reboots, add the following to /etc/sysctl.conf or /etc/sysctl.d/postgres.conf:
vm.nr_hugepages = 11500

Alternatively, echo directly into /proc/sys/vm/nr_hugepages[7]. For 1 GB pages, write to /sys/kernel/mm/hugepages/hugepages-1048576kB/nr_hugepages[6].

2. Allow the postgres user to lock large memory

Set vm.hugetlb_shm_group in /etc/sysctl.conf to the group ID of the postgres user so that processes in the group can allocate huge pages without root. Also increase the ulimit -l (maximum locked‑in memory) in systemd service files or /etc/security/limits.conf[6].

3. Check allocation

After setting vm.nr_hugepages, verify with:

grep -i huge /proc/meminfo
# Look for HugePages_Total and HugePages_Free

4. Restart PostgreSQL

Set huge_pages and optionally huge_page_size in postgresql.conf, then restart the server. The docs note that huge_pages can be try, on or off; with try, PostgreSQL falls back to normal pages if huge pages cannot be allocated, but on causes startup to fail and is recommended to catch mis‑configurations[4]. After startup, check SHOW huge_pages; it should return on (or 2MB/1GB)[9].

5. Allocate dynamic shared memory 

If you use parallel query or logical replication, set min_dynamic_shared_memory in postgresql.conf to pre‑allocate dynamic shared memory. Without this, the dynamic segments used by parallel workers will fall back to normal pages, negating part of the benefit. Since PostgreSQL 15 you can include this in the shared_memory_size_in_huge_pages calculation[3].

6. Avoid over‑allocation

Allocating too many huge pages can starve the OS; the EDB tuning guide warns that setting vm.nr_hugepages much higher than needed may prevent other services from starting or cause the server to fail to boot[10].

4  Disable Transparent Huge Pages (THP)

Transparent Huge Pages (THP) is a Linux kernel feature that tries to use huge pages automatically. For database workloads, THP often causes memory fragmentation, high latency and unpredictable performance. The PostgreSQL docs and several tuning guides strongly recommend turning it off[1][11].

How to disable THP

1. Temporarily (until reboot):

echo never | sudo tee /sys/kernel/mm/transparent_hugepage/enabled
echo never | sudo tee /sys/kernel/mm/transparent_hugepage/defrag

2. Persistent configuration

Add transparent_hugepage=never to the kernel command line (GRUB) or create a systemd service that writes never to the THP files at boot[11]. In Kubernetes clusters, set the kernel boot parameter through machine configuration or run a DaemonSet that disables THP.

THP must be disabled before enabling PostgreSQL huge pages because otherwise the kernel may map the shared memory using THP instead of the reserved huge pages, leading to inconsistent performance.[11].

5  Environment‑specific considerations

5.1  Kubernetes and containerized deployments

Kubernetes pods cannot allocate huge pages on demand; huge pages must be reserved at the node level. To use them:

  1. Configure the node’s kernel (vm.nr_hugepages or the 1 GB equivalent) as described in §3.
  2. In your pod or PostgresCluster spec, request huge page resources using resources.limits.hugepages-2Mi: <size> (or hugepages-1Gi). The Crunchy Data PostgreSQL Operator notes that you must request enough pages for all Postgres instances on the node and warns about a Kubernetes bug where Postgres may detect huge pages and attempt to use them even when not requested. Their operator defaults huge_pages=off and only sets it to try when huge page resources are requested[12].
  3. Set huge_page_size and huge_pages in the cluster or container’s PostgreSQL configuration to match the size requested (2 MB or 1 GB).
  4. Ensure min_dynamic_shared_memory is set so parallel workers can use huge pages.

5.2  Amazon RDS/Aurora PostgreSQL

AWS uses huge pages automatically on many memory‑optimized RDS instance types. Their deep‑dive documentation recommends enabling huge pages and setting huge_pages to on in the DB parameter group for large instances[13]. Because RDS manages the operating system, you cannot change vm.nr_hugepages yourself; simply set huge_pages=on in the parameter group and let RDS handle the allocation. For smaller instance types or older kernels, huge pages may not be supported; monitor SHOW huge_pages_status; after modifying the parameter group.

5.3  Azure Flexible Server for PostgreSQL

Azure’s flexible server uses Linux huge pages but does not expose kernel parameters. According to the Azure documentation, huge pages are used automatically for the shared memory area and cannot be explicitly controlled. You can set huge_pages=on in a server parameter to ensure Postgres requires huge pages and check the huge_pages_status variable for confirmation. The service disables THP by default.

5.4  Windows servers

PostgreSQL’s huge pages feature relies on Linux’s MAP_HUGETLB; it is not available on Windows. Windows provides a separate “large pages” feature that can be used by applications that call AllocateLargePages and require the “Lock pages in memory” privilege. PostgreSQL currently does not implement this (as of version 18), so you cannot use huge pages on Windows. If you need large memory pages on Windows, run Postgres inside a Linux VM or container.

6  Troubleshooting and best practices

  • Check huge_pages_status: After starting PostgreSQL, query SHOW huge_pages_status;. It will return enabled if huge pages are in use. If it says disabled by system or disabled by configuration, either the kernel lacks huge pages or the huge_pages setting is off. SHOW huge_page_size; reveals whether 2 MB or 1 GB pages are being used[6].
  • Cgroups and container limits: In cgroup‑restricted environments (e.g., Kubernetes), insufficient hugetlb cgroup limits can cause huge_pages=try to allocate huge pages but crash on the first page fault (SIGBUS). A 2024 mailing list patch proposes using MADV_POPULATE_READ to detect this situation[14]. Until it is available, ensure the container’s cgroup hugetlb limits are large enough, or set huge_pages=off when huge pages are not requested.
  • Monitor memory pressure: Huge pages are not swappable. If the server experiences memory pressure, the kernel cannot reclaim huge pages. Avoid allocating huge pages when the database rarely uses all of the reserved memory.
  • Tune shared_buffers: While huge pages reduce overhead, they do not replace good memory sizing. Best practices dictate allocating at least 25% of available system memory to shared_buffers (assuming a dedicated database server) up to a maximum of 40%.

7  Summary checklist

  1. Estimate required huge pages using postgres -C shared_memory_size_in_huge_pages (Postgres 15+) or the manual formula for older versions[3].
  2. Pre‑allocate huge pages via vm.nr_hugepages (2 MB) or /sys/kernel/mm/hugepages/hugepages-1048576kB/nr_hugepages (1 GB)[6].
  3. Set kernel permissions (vm.hugetlb_shm_group and ulimit -l) to allow the postgres user to lock memory[6].
  4. Set huge_pages=on, optionally huge_page_size = 2MB or 1GB, and configure min_dynamic_shared_memory for parallel queries[3].
  5. Disable Transparent Huge Pages by setting /sys/kernel/mm/transparent_hugepage/enabled and /defrag to never, and persist via kernel boot parameters[11].
  6. Restart PostgreSQL, verify SHOW huge_pages_status;, and adjust if necessary. Use try during testing, then switch to on once stable.
  7. Consider environment‑specific adjustments for Kubernetes, cloud services, or Windows (where huge pages are unavailable).

When configured correctly, huge pages can reduce CPU overhead and improve throughput for memory‑intensive PostgreSQL workloads. The key is to calculate the required number of pages precisely, allocate them in the kernel, disable transparent huge pages, and let PostgreSQL use them via huge_pages=on.

References

[1] PostgreSQL: Documentation: 18: 19.4. Resource Consumption

https://www.postgresql.org/docs/current/runtime-config-resource.html

[2] Tuning huge pages in Postgres

https://pganalyze.com/blog/5mins-postgres-tuning-huge-pages

[3] [7] Huge Pages and PostgreSQL | CYBERTEC PostgreSQL | Services & Support

https://www.cybertec-postgresql.com/en/huge-pages-postgresql/

[4] Improving PostgreSQL performance without making changes to PostgreSQL

https://www.enterprisedb.com/blog/improving-postgresql-performance-without-making-changes-postgresql

[5] [10] [15] PostgreSQL Performance Tuning: Optimize Your Database Server | EDB

https://www.enterprisedb.com/postgres-tutorials/introduction-postgresql-performance-tuning-and-optimization

[6] PostgreSQL: Documentation: 18: 18.4. Managing Kernel Resources

https://www.postgresql.org/docs/current/kernel-resources.html

[8] [9] Enable Huge Pages in PostgreSQL – DEV Community

https://dev.to/hujan/enable-huge-pages-in-postgresql-p7p

[11] Transparent Huge Pages Refresher

https://www.percona.com/blog/transparent-huge-pages-refresher/

[12] Huge Pages

https://access.crunchydata.com/documentation/postgres-operator/latest/guides/huge-pages

[13] ScaleSeries_RDS_PostgreSQL_DeepDive%20(1).pdf

https://pages.awscloud.com/rs/112-TZM-766/images/ScaleSeries_RDS_PostgreSQL_DeepDive%20(1).pdf

[14] PostgreSQL: Identify huge pages accessibility using madvise

https://www.postgresql.org/message-id/20240413162255.56xzlbhoolw2vyqv@ddolgov.remote.csb

Leave A Comment