work_mem
Fact — official short description: “Sets the maximum memory to be used for query workspaces.”
Identity
Lifecycle
| Fact | Value |
|---|---|
| First observed | PG9.0 (research boundary) |
| Present in | PG9.0–19 Beta 3 |
| Removed in | No |
| Introduction commit | Not asserted: predates the PG9.0 research boundary |
| Commit date | — |
| Discussion | — |
Default history
| Versions | Raw boot_val |
Unit | Human value |
|---|---|---|---|
| PG9.0–9.3 | 1024 |
kB |
1 MiB |
| PG9.4–19 Beta 3 | 4096 |
kB |
4 MiB |
How it works
work_mem is a base limit for each execution operation, not a reservation for an entire query or session. A complex plan can run several sorts or hash operations concurrently, and many sessions can do the same, so aggregate memory can be many times the configured value.
Sorts used by ORDER BY, DISTINCT, and merge joins generally use work_mem before spilling. Hash joins, hash aggregation, memoize nodes, and hash-based IN processing derive their limit from work_mem multiplied by hash_mem_multiplier.
Parallel query further multiplies exposure because resource limits such as work_mem apply to individual worker processes. The setting is therefore best understood together with plan shape, parallelism, and active-query concurrency.
Tuning advice
Advice. These are workload-specific starting points and must be validated with measurements.
| Workload | Guidance |
|---|---|
| OLTP | Keep the cluster-wide value conservative and size it against peak active backends, not the connection limit alone. Use transaction-, role-, or database-scoped overrides for known reporting jobs after checking actual spill behavior. |
| OLAP | Larger values can remove expensive sort and hash spills, but raise them with an explicit concurrency budget. Compare EXPLAIN (ANALYZE, BUFFERS) results and temporary-file statistics before and after each change. |
| Small nodes | Prefer the default or a low tens-of-megabytes setting and leave headroom for shared buffers, autovacuum, the operating system, and other processes. A single globally generous value is risky on a small host. |
Pigsty
Values use the fixed 8-vCPU, 32-GiB, 100-GiB SSD fixture and render the current Pigsty templates for PG19 Beta 3; this does not assert current Pigsty support for that historical or beta release.
| Template | Effective value | Versus upstream boot | Source expression |
|---|---|---|---|
| OLTP | 64MB |
different | {{ pg_workmem }}MB |
| OLAP | 64MB |
different | {{ pg_workmem }}MB |
| CRIT | 64MB |
different | {{ pg_workmem }}MB |
| TINY | 32MB |
different | {{ pg_workmem }}MB |
Advice — pending human review. Fact from the current Pigsty template projection: OLTP: PG9.0–19 Beta 3 = 64MB (dcs); OLAP: PG9.0–19 Beta 3 = 64MB (dcs); CRIT: PG9.0–19 Beta 3 = 64MB (dcs); TINY: PG9.0–19 Beta 3 = 32MB (dcs). Advice, pending human review — Editorial inference: the formula is intended to trade spill frequency against worst-case concurrent memory.
Common pitfalls
- Treating work_mem as a per-connection or per-query cap; it is normally available to each eligible plan operation.
- Ignoring parallel workers, which can each receive their own work_mem budget.
- Raising work_mem to fix hash spills without accounting for hash_mem_multiplier.
- Assuming temporary-table buffers are controlled here; those are governed by temp_buffers.
Related parameters
hash_mem_multiplier · temp_file_limit · log_temp_files · max_connections · max_parallel_workers_per_gather
References
- PostgreSQL 19 Beta 3 — work_mem
- PostgreSQL 18: Using EXPLAIN
- Pigsty: Parameter Optimization Policy
- PostgreSQL 19 release notes
- Machine-readable GUC export