PostgreSQLXI · Memory and Resource ManagementMemory
maintenance_work_mem and the operations that use it
What you'll learn
- List the operations that use maintenance_work_mem and how each is bounded
- Decide from evidence whether raising it will help
- Separate autovacuum_work_mem from maintenance_work_mem and know why
- Compute the aggregate commitment a large value represents
Prerequisites
Verified against PostgreSQL 18.x · PostgreSQL (comparison targets) 17.11, 16.15 · PostgreSQL (support calendar) 18, 17, 16, 15, 14 supported · pgBackRest 2.59.1 · PgBouncer 1.25.2 · Patroni 4.1.5 · Ubuntu (host baseline) 26.04 LTS · 2026-08-27
maintenance_work_mem is the allowance for operations that are
deliberate rather than continuous, and it is set generously by
convention on the reasoning that only a few run at once.
That reasoning is sound. The assumption usually attached to it — that a generous value makes those operations faster — is worth testing.
What uses it
| Operation | How the memory is used |
|---|---|
CREATE INDEX, REINDEX | The sort workspace for building the index |
VACUUM | The collection of dead tuple identifiers |
ALTER TABLE forms that rewrite | Sorting and building the new relation |
ADD FOREIGN KEY, VALIDATE CONSTRAINT | Verification workspace |
CLUSTER | Sorting the table into index order |
autovacuum_work_mem overrides it for autovacuum workers, and defaults
to -1, meaning “use maintenance_work_mem”.
Testing the index build claim
$ psql -U postgres -c "SET maintenance_work_mem='NNN'; SET max_parallel_maintenance_workers=0; CREATE INDEX ordersx_amount_idx ON ordersx (amount)" maintenance_work_mem=4MB : 874 ms
maintenance_work_mem=64MB : 1004 ms
maintenance_work_mem=1GB : 946 msNo useful difference, and the smallest setting produced the fastest run. The spread is within run-to-run variation.
Where it demonstrably matters
Vacuum, and the figure is in the output you are already reading.
INFO: finished vacuuming "postgres.public.orders": index scans: 4
From lesson VIII-01: vacuum collects dead tuple identifiers in memory, then scans every index once to remove their entries. If the collection fills before the heap scan finishes, vacuum must stop, scan every index, empty the collection, and resume.
index scans: 4 means every index on that table was read four
times. On a table with six indexes totalling 200 GB, that is 800 GB of
reading instead of 200 GB.
The aggregate commitment
maintenance_work_mem is allocated per running maintenance
operation, not once.
maintenance_work_mem × (autovacuum_max_workers + concurrent manual operations)
At 4 GB with three autovacuum workers, that is a 12 GB commitment before
any manual REINDEX is considered. Add a deployment running two
concurrent index builds and it is 20 GB.
Parallel index builds
max_parallel_maintenance_workers (default 2) lets CREATE INDEX use
workers.
Each worker gets its own share of maintenance_work_mem — the total is
divided, not multiplied, so the memory commitment does not grow with
worker count. CREATE INDEX CONCURRENTLY makes two passes over the table and waits
for older transactions between them, so it is substantially slower than
a plain build.
The measurement above disabled parallel workers deliberately, to compare memory settings rather than worker counts.
What to take from this
- Measured: no useful difference in a 2M-row index build across 4 MB, 64 MB and 1 GB. The benefit is not automatic.
index scans: NinVACUUM VERBOSEis the direct diagnostic. Above 1 means memory is the constraint.- The allowance is per operation. At 4 GB with three workers, that is a 12 GB commitment.
- Set
autovacuum_work_memseparately whenevermaintenance_work_memis large. - Parallel index build workers divide the allowance;
CONCURRENTLYdoes not use them at all. - Vacuum’s memory structure changed in 17, so pre-17 advice about a 1 GB ceiling no longer applies.
Cross-course references
- Linux for Production Sysadmins — Part XXXVII (Resource management) covers bounding a maintenance operation’s resource use at the host level, and Part XL (Memory Performance) covers what the peak actually costs.
- Ansible for Production Sysadmins — Part XLVIII (Maintenance windows and rollback) covers setting this for the duration of an operation and putting it back.
Quiz
Knowledge check · 6 questions
Q1. VACUUM VERBOSE on a large table reports 'index scans: 1'. What does raising maintenance_work_mem achieve for this table?
Q2. A cluster sets maintenance_work_mem to 4 GB so that supervised REINDEX operations run well. What exposure has this created?
Q3. Guidance from several years ago states there is no point setting maintenance_work_mem above 1 GB for vacuum. Is that still true?
Q4. Which operations draw on maintenance_work_mem? Select all that apply.
Q5. Raising maintenance_work_mem reliably speeds up index builds, since a larger sort workspace means fewer merge passes.
Q6. How would you decide whether raising maintenance_work_mem would help a specific large table?
Passing score: 75%. Answers are checked in this browser.