PostgreSQL Mastery
PostgreSQL Mastery lessons / Module 26: Memory and configuration

Memory and the settings that matter

Level 5: Internals25 min

A few settings decide most of PostgreSQL's behaviour: shared_buffers, work_mem, maintenance_work_mem, effective_cache_size, the cost settings and max_connections. Understanding what each one really controls avoids both waste and out-of-memory kills.

This lesson is interactive. Run every example on a real PostgreSQL 18 server in your browser, read EXPLAIN ANALYZE plans, and take the quiz.
Open the interactive lesson
You will learn to
  • Explain shared_buffers, work_mem, maintenance_work_mem and effective_cache_size
  • Spot sorts and hashes spilling to disk and fix them at the right scope
  • Read pg_settings: source, context and whether a restart is needed

conceptThe concept

shared_buffers: the shared page cache, typically 25% of RAM; changes need a restart. effective_cache_size: not an allocation, just a hint to the planner about how much the OS plus shared_buffers can cache (often 50-75% of RAM); higher values favour index scans.

work_mem (4 MB default) limits memory for each sort or hash operation in a query; one complex query can use several multiples, and every connection can do this at once. Hash operations may use work_mem * hash_mem_multiplier (2.0). When exceeded, sorts become "external merge" on disk and hashes split into batches. maintenance_work_mem (64 MB) is for VACUUM, CREATE INDEX and ALTER TABLE ADD FOREIGN KEY.

Planner cost settings: random_page_cost (4.0) models random I/O; on SSDs 1.1 to 1.5 is common and makes index scans more attractive. pg_settings shows each value, its unit, where it came from (source) and its context: postmaster needs a restart, sighup a reload, user can be set per session.

whyWhy it matters

work_mem set too low makes analytics sort on disk; set too high globally it lets 500 connections each use gigabytes and the kernel kills the server. Setting it per role or per session is the professional middle ground.

Use caseReal-world scenario

The reporting role gets ALTER ROLE reporting SET work_mem = '256MB', the web role keeps 8 MB, and a nightly index build runs with SET maintenance_work_mem = '2GB' in its own session.

Try itExamples

Run and edit these in the interactive lesson.

The settings that matter
SELECT name, setting, unit, context, source
FROM pg_settings
WHERE name IN ('shared_buffers', 'work_mem', 'hash_mem_multiplier', 'maintenance_work_mem', 'effective_cache_size',
               'random_page_cost', 'max_connections', 'max_wal_size', 'autovacuum_max_workers', 'max_parallel_workers_per_gather')
ORDER BY name;
A sort that spills to disk
BEGIN;
SET LOCAL work_mem = '64kB';
EXPLAIN (ANALYZE, COSTS OFF)
SELECT * FROM order_items ORDER BY unit_price DESC, order_id;
SET LOCAL work_mem = '16MB';
EXPLAIN (ANALYZE, COSTS OFF)
SELECT * FROM order_items ORDER BY unit_price DESC, order_id;
ROLLBACK;
With 64 kB the sort uses an external merge on disk; with 16 MB it is an in-memory quicksort.
Top-N sorts need little memory
BEGIN;
SET LOCAL work_mem = '64kB';
EXPLAIN (ANALYZE, COSTS OFF)
SELECT * FROM order_items ORDER BY unit_price DESC LIMIT 10;
ROLLBACK;
With LIMIT, PostgreSQL keeps only the best 10 rows in a heap, so even a tiny work_mem is enough.
Setting values at the right scope
BEGIN;
SET LOCAL random_page_cost = 1.1;
SHOW random_page_cost;
SELECT name, setting, source FROM pg_settings WHERE name = 'random_page_cost';
ROLLBACK;
SHOW random_page_cost;

internalsUnder the hood

Linux-specific: enable huge pages for large shared_buffers, avoid swap, and set vm.overcommit_memory = 2 on dedicated servers so the OOM killer does not target the postmaster. Tools such as PGTune give sane starting values from RAM, CPU and workload type.

Avoid / preferDo this, not that

Avoid
ALTER SYSTEM SET work_mem = '1GB';
Prefer
BEGIN;
SET LOCAL work_mem = '256MB';  -- only for the big report
-- run it
COMMIT;

work_mem applies per sort or hash node per query. A large global value multiplied by hundreds of connections can exhaust memory.

Avoid
shared_buffers = 48GB  # 75% of a 64 GB server
Prefer
shared_buffers = 16GB  # about 25%, the rest serves the OS page cache

PostgreSQL relies on the OS cache too; giving shared_buffers most of RAM leaves little for the OS, work_mem and connections, and double-caches data.

PitfallsCommon mistakes

  • Raising work_mem globally to fix one report. Set it for that role, session or transaction.
  • Leaving random_page_cost at 4 on SSD storage, which makes the planner avoid useful index scans.
  • Treating effective_cache_size as memory PostgreSQL allocates. It is only a planner hint.

LimitsWhen not to use it

Do not tune settings without a measured problem. Defaults plus shared_buffers, effective_cache_size and sensible work_mem cover most servers; random tuning advice often makes things worse.

SecuritySecurity notes

ALTER SYSTEM needs superuser, or since PostgreSQL 15 an explicit GRANT ALTER SYSTEM ON PARAMETER. Grant individual parameters to platform roles rather than superuser.

ChallengeTry it yourself

List every setting that is not at its built-in default, with its value, unit and where it was set.

Show one solution
One solution
SELECT name, setting, unit, source
FROM pg_settings
WHERE source NOT IN ('default', 'override')
ORDER BY name;

InterviewQuestions you should be able to answer

How do you size work_mem?
It applies per sort or hash node per query, and hashes can use hash_mem_multiplier times more, so the worst case is roughly connections times nodes per query times work_mem. Keep the global default modest (4-64 MB depending on RAM and connection count), look for spills (external merge, hash batches, temp_blks in pg_stat_statements, log_temp_files), and raise it for specific roles or sessions running analytics.
What does effective_cache_size do?
Nothing is allocated. It tells the planner how much data is likely to be cached between shared_buffers and the OS page cache, which affects the estimated cost of repeated index access. Setting it to about 50-75% of RAM on a dedicated server makes the planner more willing to use index scans.

QuizCheck your understanding

4 questions with instant feedback in the interactive lesson; a wrong answer goes into your review deck.

Go deeperOfficial documentation