io_workers
Fact — official short description: “Number of IO worker processes, for io_method=worker.”
Identity
Lifecycle
| Fact | Value |
|---|---|
| First observed | PG18 |
| Present in | PG18 |
| Removed in | PG19 Beta 3 |
| Introduction commit | 55b454d0e140 — aio: Infrastructure for io_method=worker |
| Commit date | 2025-03-18 |
| Discussion | thread 1 · thread 2 · thread 3 |
Default history
| Versions | Raw boot_val |
Unit | Human value |
|---|---|---|---|
| PG18 | 3 |
— | 3 |
How it works
io_workers sets the number of dedicated I/O worker processes used by PostgreSQL 18 when io_method=worker. It has no effect for io_uring or sync.
I/O workers execute asynchronous requests on behalf of database processes; this is an execution pool, distinct from parallel query workers and background worker slots.
Changing the count is reloadable, but useful capacity still depends on io_max_concurrency, workload queue depth, storage latency, and CPU. More workers do not guarantee more device throughput. Its SIGHUP context allows configuration reload without a server restart.
Tuning advice
Advice. These are workload-specific starting points and must be validated with measurements.
| Workload | Guidance |
|---|---|
| OLTP | Tune io_workers only when io_method=worker. Start from the PG18 default 3, measure worker saturation, CPU use, and tail latency, and increase the pool only when queued eligible I/O waits for worker execution rather than for the device. |
| OLAP | Sustained eligible scans can benefit from enough I/O workers to feed storage, but extra processes add scheduling overhead and cannot exceed the per-process or device concurrency bottleneck. Compare throughput and worker utilization; request size is controlled elsewhere. |
| Small nodes | Keep 3 or a measured smaller value when process and CPU budgets are tight. io_workers has no effect under io_uring or sync, so never spend tuning effort on it until io_method is confirmed as worker. |
Pigsty
Values use the fixed 8-vCPU, 32-GiB, 100-GiB SSD fixture and render the current Pigsty templates for PG18; this does not assert current Pigsty support for that historical or beta release.
| Template | Effective value | Versus upstream boot | Source expression |
|---|---|---|---|
| OLTP | 4 |
different | {{ pg_io_workers }} |
| OLAP | 4 |
different | {{ pg_io_workers }} |
| CRIT | 4 |
different | {{ pg_io_workers }} |
| TINY | 3 |
same as boot | {{ pg_io_workers }} |
Advice — pending human review. Fact from the current Pigsty template projection: OLTP: PG18 = 4 (dcs); OLAP: PG18 = 4 (dcs); CRIT: PG18 = 4 (dcs); TINY: PG18 = 3 (dcs). Advice, pending human review — Editorial inference, pending maintainer review: The resolved worker pool gives PG18’s worker AIO method more executors on non-tiny profiles while keeping the tiny profile at the upstream boot count.
Common pitfalls
- Changing io_workers while io_method is io_uring or sync, where it has no effect.
- Treating worker-process count as bytes per request or as the per-process I/O ceiling.
- Adding workers when the storage device, not the worker pool, is already saturated.
- Forgetting that the reloadable pool still consumes process slots, CPU, and scheduling capacity.
Related parameters
io_method · io_max_concurrency · effective_io_concurrency · maintenance_io_concurrency · max_worker_processes