# max_parallel_workers_per_gather

> max_parallel_workers_per_gather — Sets the maximum number of parallel processes per executor node. Observed in PG9.6–19 Beta 3; its last measured boot default is 2 in PG19 Beta 3, with user context. This is a beta-snapshot fact and can change before PostgreSQL 19 GA.
---

> [!NOTE]
> **Fact — official short description:** “Sets the maximum number of parallel processes per executor node.”

## Identity {#identity}

| Field | Value | Meaning |
| --- | --- | --- |
| Type | `integer` | Upstream pg_settings type |
| Context | `user` | Settable by an ordinary user |
| Unit | — | Raw unit |
| Range | `0` – `1024` | Raw limits in the last observed version |
| Enum values | — | — for non-enum types |
| Category | Resource Usage / Worker Processes | Upstream classification |
| Latest boot value | `2` | 2 |
{.fields meta="-"}

## Lifecycle {#lifecycle}

| Fact | Value |
| --- | --- |
| First observed | PG9.6 |
| Present in | PG9.6–19 Beta 3 |
| Removed in | No |
| Introduction commit | [`c9ce4a1c61eb`](https://git.postgresql.org/gitweb/?p=postgresql.git;a=commit;h=c9ce4a1c61ebf39c03885cc19fe7c32edc04a300) — Eliminate "parallel degree" terminology. |
| Commit date | 2016-06-09 |
| Discussion | — |

## Default history {#default-history}

| Versions | Raw `boot_val` | Unit | Human value |
| --- | --- | --- | --- |
| PG9.6 | `0` | — | 0 |
| PG10–19 Beta 3 | `2` | — | 2 |
{.full-width caption="Measured PG9.0–19 Beta 3 boot defaults"}

## How it works {#mechanism}

max_parallel_workers_per_gather limits how many workers one Gather or Gather Merge node may request. Zero prevents parallel query execution through these nodes without disabling other background workers.

Workers are not reserved and can be unavailable at execution time because max_parallel_workers and max_worker_processes are shared pools. The leader process is not included in this numeric limit.

Each parallel plan can multiply work_mem-limited nodes, CPU demand, and I/O. The planner weighs parallel_setup_cost and parallel_tuple_cost before deciding whether to request workers. Its user context permits session- or transaction-local changes; newly performed or newly planned work sees the value.

## Tuning advice {#tuning-advice}

> [!TIP]
> **Advice.** These are workload-specific starting points and must be validated with measurements.

| Workload | Guidance |
| --- | --- |
| OLTP | Set max_parallel_workers_per_gather from a concurrency budget, not core count alone. Protect latency-sensitive OLTP from report and maintenance bursts, and verify actual Workers Planned versus Workers Launched. |
| OLAP | Analytical work can use a larger max_parallel_workers_per_gather, but multiply per-node memory and I/O by concurrent statements. Benchmark throughput under realistic worker contention rather than one isolated query. |
| Small nodes | Keep max_parallel_workers_per_gather conservative on a small host. More possible workers can reduce throughput through context switching and memory pressure even when a single query becomes faster. |
{.full-width}

## Pigsty {#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 | `2` | same as boot | `{{ pg_max_parallel_workers_per_gather\|int }}` |
| OLAP | `4` | different | `{{ pg_max_parallel_workers_per_gather\|int }}` |
| CRIT | `0` | different | `{{ pg_max_parallel_workers_per_gather\|int }}` |
| TINY | `0` | different | `{{ pg_max_parallel_workers_per_gather\|int }}` |
{.full-width}

> [!CAUTION]
> **Advice — pending human review.** Fact from the current Pigsty template projection: OLTP: PG9.6–19 Beta 3 = 2 (dcs); OLAP: PG9.6–19 Beta 3 = 4 (dcs); CRIT: PG9.6–19 Beta 3 = 0 (dcs); TINY: PG9.6–19 Beta 3 = 0 (dcs). Advice, pending human review — Editorial inference, pending maintainer review: The values allow modest OLTP and stronger OLAP query parallelism while explicitly suppressing Gather workers in crit and tiny profiles.

## Common pitfalls {#common-pitfalls}

- Treating max_parallel_workers_per_gather as reserved capacity rather than an upper bound shared with other work.
- Ignoring that parallel plans multiply CPU, I/O, and work_mem-limited nodes.
- Benchmarking one query without concurrent worker contention.
- Assuming planned workers will always be launched at execution time.

## Related parameters {#related-parameters}

[`max_parallel_workers`](/parameters/max-parallel-workers/) · [`max_worker_processes`](/parameters/max-worker-processes/) · [`parallel_setup_cost`](/parameters/parallel-setup-cost/) · [`parallel_tuple_cost`](/parameters/parallel-tuple-cost/) · [`parallel_leader_participation`](/parameters/parallel-leader-participation/) · [`work_mem`](/parameters/work-mem/)

## References {#references}

- [PostgreSQL 19 Beta 3 — max_parallel_workers_per_gather](https://www.postgresql.org/docs/19/runtime-config-resource.html#GUC-MAX-PARALLEL-WORKERS-PER-GATHER)
- [PostgreSQL 19 release notes](https://www.postgresql.org/docs/19/release-19.html)
- [Machine-readable GUC export](/data/guc.jsonl)
