PostgreSQLIII · Configuration ArchitectureConfiguration
Settings contexts, and planning a change from them
What you'll learn
- Name all seven settings contexts and what each one requires to change
- Predict from the context whether a change needs a reload, a restart or neither
- Explain why backend-context parameters apply only to new connections
- Group a set of proposed changes into the minimum number of outage windows
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
PostgreSQL 18 has 399 configuration parameters, and every one of them
declares what it takes to change it. That declaration is the context
column of pg_settings, and it is the single most useful piece of
metadata in the whole configuration system, because it converts “can we
change this?” from a discussion into a lookup.
The seven contexts
$ psql -U postgres -c 'SELECT context, count(*) FROM pg_settings GROUP BY context ORDER BY count(*) DESC' context | count
-------------------+-------
user | 151
sighup | 104
postmaster | 69
superuser | 49
internal | 20
superuser-backend | 4
backend | 2
(7 rows)| Context | To change it | Affects |
|---|---|---|
internal | Cannot be changed. Fixed at compile or initdb time | — |
postmaster | Edit and restart | Everything |
sighup | Edit and reload | Everything, immediately |
superuser-backend | Reload, or supply at connection time | New connections only |
backend | Reload, or supply at connection time | New connections only |
superuser | SET in a session, by a superuser | That session |
user | SET in a session, by anyone | That session |
The good news for change planning is in the distribution. 200 of the
399 parameters are user or superuser — settable live, in a session,
with no coordination at all. Another 104 are sighup, needing only a
reload. Only 69 parameters require a restart.
That ratio is worth carrying into conversations with change boards. The default assumption that “a database configuration change means an outage” is wrong for roughly five parameters out of six.
internal: the read-only ones
$ psql -U postgres -c "SELECT name, setting FROM pg_settings WHERE context = 'internal' ORDER BY name LIMIT 8" name | setting
-----------------------+---------
block_size | 8192
data_checksums | on
data_directory_mode | 0700
in_hot_standby | off
integer_datetimes | on
max_function_args | 100
max_identifier_length | 63
segment_size | 131072Illustrative output
These are reports, not controls. block_size is 8192 because the
binary was compiled that way. data_checksums reflects what initdb
decided, which is why the previous part’s lesson had to reach for
pg_checksums to change it. in_hot_standby tells you whether this
server is a standby.
Attempting to set one produces an error rather than a silent no-op, which is the correct behaviour and worth relying on.
The two backend contexts
These are the ones that surprise people, and they account for six parameters — including two that operators reach for constantly.
$ psql -U postgres -c "SELECT name, context FROM pg_settings WHERE context LIKE '%backend' ORDER BY context, name" name | context
-----------------------+-------------------
ignore_system_indexes | backend
post_auth_delay | backend
jit_debugging_support | superuser-backend
jit_profiling_support | superuser-backend
log_connections | superuser-backend
log_disconnections | superuser-backend
(6 rows)A backend-context parameter is read once, when a backend starts, and fixed for that backend’s lifetime. A reload updates the value the server will hand to future backends, and changes nothing about the ones already running.
Reading the context before proposing a change
# The change-planning query. Run it for the parameters you intend to touch.
psql -U postgres -c \
"SELECT name, setting, unit, context, pending_restart
FROM pg_settings
WHERE name IN ('shared_buffers','work_mem','max_connections',
'log_min_duration_statement','max_wal_size',
'autovacuum_max_workers')
ORDER BY context, name"
$ psql -U postgres -c 'SELECT name, setting, unit, context FROM pg_settings ORDER BY context, name' name | setting | unit | context
----------------------------+---------+------+------------
max_connections | 100 | | postmaster
shared_buffers | 16384 | 8kB | postmaster
autovacuum_max_workers | 3 | | sighup
max_wal_size | 1024 | MB | sighup
log_min_duration_statement | -1 | ms | superuser
work_mem | 4096 | kB | userIllustrative output
That single query turns six proposals into a plan: two of them can be done now, two at the next reload — which is also now, since a reload is not disruptive — and two need to be batched into whatever restart window comes next.
The version dimension
Contexts change between major versions, and a runbook that assumes one is version-specific whether or not it says so.
The clearest recent example is autovacuum_max_workers. On 18.6 it is
sighup context — adjustable live, up to the
autovacuum_worker_slots ceiling, which is itself postmaster and set
at startup. That pairing of a live-adjustable setting with a
restart-only ceiling is new in 18, and a runbook written against an
older release will assume a restart is needed where it is not.
Check the context on the cluster in front of you rather than trusting a runbook’s memory of it:
SELECT name, setting, context FROM pg_settings
WHERE name IN ('autovacuum_max_workers','autovacuum_worker_slots');
$ psql -U postgres -c "SELECT name, setting, context FROM pg_settings WHERE name LIKE 'autovacuum%worker%' ORDER BY name" name | setting | context
-------------------------+---------+------------
autovacuum_max_workers | 3 | sighup
autovacuum_worker_slots | 16 | postmaster
(2 rows)For an estate spanning versions, that difference decides whether an autovacuum emergency at 03:00 can be addressed without an outage. The runbook has to read the context rather than assert it, which is the same discipline as reading the file paths rather than hard-coding them.
Production discipline
- Read
contextbefore writing the change request. Five parameters out of six do not need a restart, and the default assumption that they do costs real time. - Do reload-level changes separately and early. They are individually reversible in seconds; batching them into a restart window forfeits that.
- Treat
superuser-backendandbackendas “new connections only”. Enabling connection logging during an incident says nothing about the sessions already open. - Do not assert a context in a runbook. It changes between major
versions —
autovacuum_max_workersmoved frompostmastertosighupin 18 — so the runbook should read it. - Plan
max_connectionsandmax_locks_per_transactiontogether. They size the same shared structure and raising one without the other is how an out-of-shared-memory error appears weeks later.
Cross-course references
- Git, CI/CD & GitOps — Part CVI (Change management) covers stating the blast radius and rollback of a change, and the context column is the input to both for a database parameter.
- Ansible for Production Sysadmins — Part XVI (Handlers) covers triggering a reload rather than a restart when a template changes, which is the automated form of this lesson’s central distinction.
- Linux for Production Sysadmins — Part XXXVII (Resources) covers
the kernel shared-memory limits that the
postmasterparameters ultimately consume.
Quiz
Knowledge check · 6 questions
Q1. During an incident with 90 sessions holding the connection pool, an operator enables log_connections and reloads. Nothing appears in the log for those sessions. Why?
Q2. Roughly what proportion of PostgreSQL 18's configuration parameters require a restart to change?
Q3. Which statements about settings contexts are correct? Select all that apply.
Q4. A parameter with user context can be changed by an ordinary role for the duration of its own session, without any privilege.
Q5. Explain why max_connections and max_locks_per_transaction should be planned together, and what failure appears if they are not.
Q6. Produce the change plan and justify the sequencing.
A team has six pending PostgreSQL configuration changes and has raised a single change request asking for a two-hour outage window in three weeks to apply all of them together. The changes are: raise shared_buffers from 128MB to 8GB; raise max_connections from 100 to 300; raise max_wal_size from 1GB to 8GB; raise autovacuum_max_workers from 3 to 6; enable log_min_duration_statement at 1000ms; and raise the default work_mem from 4MB to 16MB. The cluster runs PostgreSQL 18.6 and is currently suffering from checkpoints triggered by WAL volume and from autovacuum falling behind.
Passing score: 75%. Answers are checked in this browser.