PostgreSQL · shared memory · hugetlb · sizing

How many huge pages
does PostgreSQL actually need?

Since PostgreSQL 15 the server answers that itself: shared_memory_size_in_huge_pages. And the answer is dominated by one setting — as a rule of thumb, shared memory is shared_buffers plus about 2 % of overhead for describing it, plus a per-backend tail. Everything else is a footnote until you make it extreme, which is exactly why the sizing is boring and the failure modes are not. This page computes that number for a configuration you do not run yet, and answers the question the docs skip — how much margin to put into vm.nr_hugepages, and why the honest answer is "not much".

THE CALCULATOR

Put in your own numbers

The same sum PostgreSQL does at startup in CalculateShmemSize(): buffers and their descriptors, lock tables, SLRU caches, WAL buffers, per-backend arrays. Useful when you want to size a configuration you are not running yet — a bigger shared_buffers, or a server you have not built.

What this is for. An illustration, not an oracle. Watch each setting move the number and you will see the point: it is shared_buffers plus about 2 % of overhead, and everything else shifts it by a few pages. So padding vm.nr_hugepages by 10 % "just in case" is not caution — it is gigabytes taken from the page cache to cover a number the server already knows exactly. Take the real value with SHOW shared_memory_size_in_huge_pages, add a percent or two, and recompute when the configuration changes.
Configuration
2 MB pages
32 GB
300
64
2 %
everything else that counts
max_worker_processes
max_wal_senders
autovacuum_max_workers
max_prepared_transactions
max_pred_locks_per_transaction
track_activity_query_size (bytes)
wal_buffers (MB, 0 = auto, server max 2047)
min_dynamic_shared_memory (MB)
transaction_buffers (8 kB blocks, 0 = auto)
pg_stat_statements.max (0 = not preloaded)
shared_memory_size_in_huge_pages
shared_memory_size
reserve — vm.nr_hugepages
hover a row for the matching pg_shmem_allocations names
what to write on the machine
Only the main segment. This number covers the one shared memory segment the postmaster creates at startup — the one huge_pages applies to. Memory allocated later per backend (work_mem, maintenance_work_mem, catalog and plan caches) is not in it, and does not use huge pages. So do not add anything to the reservation for it.
THE CHECK

Calculator versus postgres -C

Twelve configurations run through the server itself on PostgreSQL 17, across the full range the sliders allow — shared_buffers from 8 GB to 1 TB, max_connections from 100 to 10 000, max_locks_per_transaction from 64 to 256 — then the same inputs put through the calculator. Two of them also load pg_stat_statements; everything else stays at its default.

What is compared is the requirement itself, shared_memory_size_in_huge_pages. The margin slider is left out: postgres -C reports what the server needs, while the vm.nr_hugepages line is that number plus whatever slack you add on top.

how the right-hand column was produced
$ postgres -D /tmp/d -C shared_memory_size_in_huge_pages \
      -c shared_buffers=1024GB -c max_connections=10000 -c max_locks_per_transaction=4096 …
Configurationcalculatorpostgres -CΔΔ memory
shared_buffers 8 GB · max_connections 100 · locks 644 2174 218−0.02 %−2 MB
shared_buffers 8 GB · max_connections 10 000 · locks 2564 8254 826−0.02 %−2 MB
shared_buffers 32 GB · max_connections 100 · locks 6416 78416 788−0.02 %−8 MB
shared_buffers 32 GB · max_connections 1 000 · locks 12816 81716 821−0.02 %−8 MB
shared_buffers 32 GB · max_connections 10 000 · locks 25617 39217 396−0.02 %−8 MB
shared_buffers 32 GB · max_connections 300 · pg_stat_statements max 500016 79016 794−0.02 %−8 MB
shared_buffers 128 GB · max_connections 500 · locks 6467 06366 975+0.13 %+176 MB
shared_buffers 128 GB · max_connections 5 000 · locks 25667 35667 268+0.13 %+176 MB
shared_buffers 128 GB · max_connections 1 000 · pg_stat_statements max 10 00067 07566 988+0.13 %+174 MB
shared_buffers 512 GB · max_connections 1 000 · locks 128268 159267 352+0.30 %+1 614 MB
shared_buffers 1 TB · max_connections 100 · locks 64536 224534 457+0.33 %+3 534 MB
shared_buffers 1 TB · max_connections 10 000 · locks 256536 832535 065+0.33 %+3 534 MB