Skip to main content
RunBook Academy

PostgreSQLIII · Configuration ArchitectureConfiguration

ALTER SYSTEM, and how it fails

Advanced⏱ ~25 minpsql

What you'll learn

  • Describe what ALTER SYSTEM writes and where
  • Enumerate the errors ALTER SYSTEM raises and, critically, the one it does not
  • Explain why a restart-only change is a deferred risk rather than an immediate one
  • Decide whether ALTER SYSTEM should be permitted in a managed estate

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

Not yet marked complete on this device.

ALTER SYSTEM is the supported way to change server configuration from a SQL connection, without shell access to the host. It is genuinely useful — a managed service or a locked-down host may offer no other route — and it has one failure mode serious enough to justify a lesson of its own.

What it does

It writes a single key to postgresql.auto.conf in the data directory, rewriting that file wholesale each time. The file is read last, after postgresql.conf and everything it includes, so an ALTER SYSTEM entry overrides them.

ALTER SYSTEM SET max_wal_size = '4GB';   -- write it
ALTER SYSTEM RESET max_wal_size;         -- remove that one key
ALTER SYSTEM RESET ALL;                  -- empty the file

It does not apply the change. Applying still requires a reload for a sighup parameter or a restart for a postmaster one, exactly as if you had edited the file by hand.

The errors it does raise

These are all rejections at statement time, which is the helpful case:

Read-only / Safefour things ALTER SYSTEM refuses
$ psql -U postgres  # four separate ALTER SYSTEM attempts
-- inside a transaction block
ERROR:  ALTER SYSTEM cannot run inside a transaction block

-- a value that does not parse
ALTER SYSTEM SET work_mem = 'banana';
ERROR:  invalid value for parameter "work_mem": "banana"

-- a read-only parameter
ALTER SYSTEM SET block_size = 16384;
ERROR:  parameter "block_size" cannot be changed

-- a parameter that does not exist
ALTER SYSTEM SET not_a_real_parameter = 1;
ERROR:  unrecognized configuration parameter "not_a_real_parameter"

The transaction-block rejection is worth remembering practically: it means several ALTER SYSTEM statements cannot be passed in one psql -c argument, because psql wraps multiple statements in a single transaction. Use a separate -c for each.

The error it does not raise

ALTER SYSTEM validates that a value is syntactically legal for the parameter. It does not validate that the machine can satisfy it.

The parameters where this bites are the postmaster-context ones that size shared memory: shared_buffers, max_connections, max_locks_per_transaction, wal_buffers, max_worker_processes. A sighup parameter set to an unreasonable value is far less dangerous, because the reload applies it immediately and you find out at once.

Disabling ALTER SYSTEM

PostgreSQL provides a parameter to turn the command off entirely.

Read-only / Safeallow_alter_system
$ psql -U postgres -c "SELECT name, setting, context, short_desc FROM pg_settings WHERE name = 'allow_alter_system'"
        name        | setting | context |                short_desc
--------------------+---------+---------+------------------------------------------
allow_alter_system | on      | sighup  | Allows running the ALTER SYSTEM command.
(1 row)

Setting it to off — in postgresql.conf, not via ALTER SYSTEM — makes the command raise an error. This is worth doing in one specific situation: an estate where configuration is owned by Ansible, Terraform or a GitOps pipeline, and where an ALTER SYSTEM made during an incident would silently diverge the running server from the repository that everyone believes describes it.

It is explicitly not a security control. The documentation is direct about this: a superuser has many other ways to change server behaviour, so this prevents accident and drift rather than a determined actor. Treat it as a guard rail, in the same category as a protected branch.

Production discipline

  1. Check pending_restart immediately after every ALTER SYSTEM. It is the only signal distinguishing a change that is live from one that is merely written.
  2. Never leave a restart-only change pending indefinitely. Restart in a window you chose rather than discovering the outcome during an unplanned one.
  3. Treat ALTER SYSTEM on shared-memory parameters as the highest-risk configuration action available, because it is the one whose failure is deferred and total.
  4. Use one -c per ALTER SYSTEM. Several statements in a single -c become one transaction, which the command refuses.
  5. Consider allow_alter_system = off where configuration is managed as code, as a drift guard rail rather than a security control.
  6. Editing postgresql.auto.conf by hand is legitimate exactly once: when the server will not start because of what is in it.

Cross-course references

  • Git, CI/CD & GitOps — Part LXXV (Drift) covers the divergence between a repository and a running system that allow_alter_system exists to prevent, and Part CVI (Change management) covers stating a rollback for a change whose effect is deferred.
  • Ansible for Production Sysadmins — Part XXXVI (Drift) covers detecting and correcting exactly this class of out-of-band change.
  • Linux for Production Sysadmins — Part XXXVII (Resources) and Part XL (Memory performance) cover the shared-memory limits that the failure in this lesson runs into.

Quiz

Knowledge check · 6 questions

  1. Q1. An operator runs ALTER SYSTEM SET shared_buffers = '999GB' on an ordinary server, reloads, and sees no error. What is the state of the cluster?

  2. Q2. A cluster will not start because a value written by ALTER SYSTEM is impossible. What is the correct recovery?

  3. Q3. Which of these does ALTER SYSTEM reject at statement time? Select all that apply.

  4. Q4. Setting allow_alter_system to off is a security control that prevents a superuser from changing server configuration.

  5. Q5. Explain why a restart-only parameter is riskier to set via ALTER SYSTEM than a reload-level one, and name the column that reveals the pending state.

  6. Q6. Diagnose and give both the immediate recovery and the process change.

    At 02:40 a host reboots after a hypervisor fault. PostgreSQL does not come back. The log shows a FATAL error about mapping anonymous shared memory, with a hint mentioning shared_buffers and max_connections. The on-call engineer confirms nobody has touched the database in weeks and the last change record is 41 days old. The monitoring history shows the cluster ran normally for the entire 41 days. The host has 64 GB of memory and postgresql.conf reads shared_buffers = 16GB.

Passing score: 75%. Answers are checked in this browser.