To reload PostgreSQL’s configuration without a restart, run pg_ctl -D /path/to/data reload as the OS user that owns the data directory, or run SELECT pg_reload_conf(); as a superuser in psql. systemctl reload postgresql on Debian and Ubuntu, or kill -HUP on the postmaster, does the same thing. Each makes the postmaster re-read postgresql.conf, postgresql.auto.conf, pg_hba.conf and pg_ident.conf and pass the signal to all running server processes, so no connection is dropped. Settings that can only be set at server start, such as shared_buffers, max_connections and wal_level, keep their old value until you restart; pg_settings.pending_restart and the server log show which ones were skipped.
This applies to PostgreSQL 14 through 18, the supported releases as of October 2026 (19 is in beta; 14 reaches end of life on November 12, 2026). I ran the pg_ctl, SQL and kill commands on PostgreSQL 17.11 on macOS and checked them against the 18 documentation. I did not run the Debian and Ubuntu steps; they come from the postgresql-common unit files and documentation.
Table of Contents
Reload PostgreSQL config with pg_ctl reload
Pass -D unless PGDATA is set in your shell; the pg_ctl reference requires one or the other:
$ pg_ctl reload
pg_ctl: no database directory specified and environment variable PGDATA unset
Try "pg_ctl --help" for more information.
$ pg_ctl -D /path/to/data reload
server signaled
A stopped server gives PID file ".../postmaster.pid" does not exist. To find the right directory, ask the server (superuser or pg_read_all_settings only):
SHOW data_directory;
SHOW config_file;
SHOW hba_file;
On Debian and Ubuntu, pg_ctl lives under /usr/lib/postgresql/<version>/ and is wrapped as pg_ctlcluster, so use sudo pg_ctlcluster 18 main reload; pg_lsclusters lists each cluster’s data directory.
Reload Postgres config from psql with pg_reload_conf()
Superusers can call pg_reload_conf(), and GRANT EXECUTE ON FUNCTION pg_reload_conf() TO role_name; extends that to another role. The t it returns means only that the signal was sent, not that the files were valid:
postgres=# SELECT pg_reload_conf();
pg_reload_conf
----------------
t
(1 row)
ALTER SYSTEM writes a setting to postgresql.auto.conf, and the reload applies it:
ALTER SYSTEM SET work_mem = '8MB';
SELECT pg_reload_conf();
Reload with systemctl reload postgresql or kill -HUP
On Debian and Ubuntu, sudo systemctl reload postgresql reloads every cluster set to start automatically, and sudo systemctl reload postgresql@18-main reloads one. The postgresql unit is only a meta unit; each cluster unit declares ReloadPropagatedFrom=postgresql.service, which forwards the reload. Other packages name the unit differently (systemctl list-units 'postgresql*' shows yours); the example unit in the server documentation implements reload as ExecReload=/bin/kill -HUP $MAINPID.
To send the signal yourself, the postmaster’s PID is the first line of postmaster.pid:
kill -HUP "$(head -1 /path/to/data/postmaster.pid)"
Which settings need a restart instead of a reload (pending_restart)
A setting’s context in pg_settings decides what a reload does. Many settings need only a reload, including log_min_duration_statement, which is how you start logging slow statements without a restart.
| context | After a reload | Examples |
|---|---|---|
postmaster |
Ignored until a restart | shared_buffers, max_connections, wal_level, listen_addresses |
sighup |
Applied everywhere | max_wal_size, checkpoint_timeout, log_line_prefix |
superuser, user |
Applied to existing sessions, except those that ran SET for that setting |
work_mem, log_min_duration_statement |
superuser-backend, backend |
New connections only | log_connections, log_disconnections |
List every restart-only setting on your server:
SELECT name, context FROM pg_settings WHERE context = 'postmaster' ORDER BY name;
After a reload, skipped settings are flagged; setting still shows the running value (16384 blocks of 8kB, or 128MB):
postgres=# SELECT name, setting, pending_restart FROM pg_settings WHERE pending_restart;
name | setting | pending_restart
----------------+---------+-----------------
shared_buffers | 16384 | t
(1 row)
A restart (pg_ctl -D /path/to/data restart or systemctl restart) clears the flag. A setting’s context can change between releases: autovacuum_max_workers needs a restart on 14 to 17 but only a reload on 18, which added the restart-only autovacuum_worker_slots as its ceiling.
I put the core steps in a script that builds a throwaway cluster on port 55432, runs them and deletes the cluster afterwards; it needs initdb, pg_ctl and psql on your PATH.
Check that the reload took effect
The postmaster logs each reload and each value it changes:
LOG: received SIGHUP, reloading configuration files
LOG: parameter "work_mem" changed to "8MB"
To see where a live value comes from, read source, sourcefile and sourceline in pg_settings (the last two need a superuser or pg_read_all_settings):
SELECT name, setting, source, sourcefile, sourceline
FROM pg_settings WHERE name = 'work_mem';
A sourcefile ending in postgresql.auto.conf means an ALTER SYSTEM value is overriding your edit, and a source of database, user or session means an ALTER DATABASE ... SET, ALTER ROLE ... SET or plain SET wins.
To catch mistakes before you reload, query pg_file_settings, which reads the files as they are now (superusers only, by default). A restart-only change shows up there too, as setting could not be applied:
SELECT sourcefile, sourceline, name, setting, error
FROM pg_file_settings WHERE error IS NOT NULL;
After the reload, SELECT pg_conf_load_time(); shows when the server last loaded the files; it doesn’t move after a syntax error. The log explains anything that didn’t apply:
| Log line | What it means |
|---|---|
parameter "shared_buffers" cannot be changed without restarting the server |
A postmaster setting: the new value is ignored until a restart, and pending_restart is true. |
invalid value for parameter "work_mem": "8XB" |
That line is rejected and the rest of the file applies (unaffected changes were applied). |
syntax error in file "..." line 850 or unrecognized configuration parameter "work_memm" |
Nothing in the file applies, valid lines included (no changes were applied). |
parameter "work_mem" removed from configuration file, reset to default |
You deleted or commented out the line, so the setting fell back to the built-in default. |
A reload only logs a bad value or a syntax error and carries on with the old values, but a restart refuses to start on the same file (FATAL: configuration file "..." contains errors), so fix it now rather than at the next restart.
To find the log, SELECT pg_current_logfile(); returns its path while the logging collector is on. pg_lsclusters prints it on Debian and Ubuntu, and the Homebrew service writes to $(brew --prefix)/var/log/postgresql@18.log.
Reload pg_hba.conf without a restart
The same reload re-reads pg_hba.conf, so no restart is needed (on Windows, new connections pick up changes without a reload, as the documentation notes). Check the file first; pg_hba_file_rules reads it as it is now:
SELECT line_number, error FROM pg_hba_file_rules WHERE error IS NOT NULL;
If a line is bad, the reload logs the error and pg_hba.conf was not reloaded, and the server keeps the previous rules. A restart would fail with FATAL: could not load .../pg_hba.conf. A good reload logs nothing beyond the SIGHUP line.