Not satisfied with the instructions I found on setting up Linux HugePages for PostgreSQL, I wrote my own for our team.
Inside psql:
postgres=# select name, setting from pg_settings where name like '%huge%';
name | setting
---------------------------------+---------
huge_page_size | 0
huge_pages | try
huge_pages_status | off
shared_memory_size_in_huge_pages | 72
Note the last line above. It’s much better to go by shared_memory_size_in_huge_pages than by shared_buffers, which is only part of the shared memory used by the Postgres instance (albeit the biggest part).
As root on the OS, try to set HugePages to 1 plus shared_memory_size_in_huge_pages:
# echo 73 > /proc/sys/vm/nr_hugepages; cat /proc/sys/vm/nr_hugepages
If cat shows less than you want, 73 here, try a few more times. If it's still less, you have to reboot because there's not enough contiguous free memory. But put vm.nr_hugepages = 73 in /etc/sysctl.conf before you reboot.[note1]
If you get 73, then
# grep ^Huge /proc/meminfo
It should show HugePages_Total, HugePages_Free, and HugePages_Rsvd as 73, 73, 0, respectively.
Bounce Postgres (we’re using version 17; the service name is found by systemctl list-units|grep progresql, if you don’t remember it):
# systemctl restart postgresql-17
Check HugePages again. HugePages_Free should be smaller and HugePages_Rsvd should be only 1 smaller than it, e.g.
# grep ^Huge /proc/meminfo HugePages_Total: 73 HugePages_Free: 65 HugePages_Rsvd: 64 ...
The difference between HugePages_Free and HugePages_Rsvd is the wastage (we intentionally waste 1 page as a guard), because HugePages_Free includes reserved but not actually used memory.[note2]
And inside psql, the query against pg_settings should show on for huge_pages_status.
If you have not done so, as root, add vm.nr_hugepages = 73 to /etc/sysctl.conf so HugePages will be reserved on future reboots.
Lastly, transparent HugePages causes sporadic CPU spikes, non-contiguous memory chunks, and other problems. It's strongly recommended we disable it. The new way to do so is
grubby --args="transparent_hugepage=never" --update-kernel ALLfollowed by reboot. Before and after reboot, you can check by
If you change shared_buffers in Postgres, check the pg_settings view again to get a new shared_memory_size_in_huge_pages, and set HugePages at the OS level accordingly again.
In case you ask why HugePages: These memory pages are locked in system memory and have much bigger page size than the default, so it benefits software programs that demand a large amount of memory such as a database. Using HugePages reduces sys (kernel) CPU usage thus improves system performance.
__________________________
[note1]
Ideally, you need to do more work to ensure HugePages is properly set up. For example, postgres soft memlock limit and postgres hard memlock limit should be added to /etc/security/limits.conf, where limit can just be the system memory in KB to make it simple (it's meaningless but harmless to set it bigger than that).
In /etc/sysctl.conf, kernel.shmmax should be set to a large number, which can be system memory in bytes (note: not KB!).
session required pam_limits.so should be added to /etc/pam.d/login.
But if HugePages already works, these settings become optional.
[note2]
To understand the 3 lines of HugePages_* in /proc/meminfo, look at this simple diagram
UUUUUFFFF <-- Total split into really used (U) and free (F) UUUUURRR. <-- Total split into really used (U), reserved (R) and really free (.)If one letter or dot is one HugePage, the above says
HugePages_Total: 9 HugePages_Free: 4 HugePages_Rsvd: 3and you’ll have 4–3=1 page completely wasted.
August 2026
(originally posted on LinkedIn)
Contact me
To my Computer Page