Safely Start and Stop a Debian PostgreSQL Cluster with pg_ctlcluster
You will use pg_ctlcluster to inspect and control one Debian PostgreSQL cluster, while keeping ordinary reloads separate from disruptive stops and restarts. Allow about ten minutes for a routine check, or longer if you need to investigate a failed start. The examples match postgresql-common version 257build1.1 and the installed pg_ctlcluster(1) manual.
The route
Jump straight to the step you need, or tick off Done means at the end.
You need the cluster version and name, the postgresql-common package, and either the database cluster owner or root. On this system the example cluster is version 16, named main. Substitute your own values after checking them. Do not guess a cluster name from a directory path.
1. Find the exact cluster identity
Use pg_lsclusters to list the clusters managed by Debian's PostgreSQL tooling. This is a read-only command and normally needs no elevated privileges:
$ pg_lsclusters
Ver Cluster Port Status Owner Data directory Log file
16 main 5432 online postgres /var/lib/postgresql/16/main /var/log/postgresql/postgresql-16-main.log
The two values needed by pg_ctlcluster are the first two columns: 16 and main. The command's main form is pg_ctlcluster VERSION NAME ACTION. Debian also accepts pg_ctlcluster VERSION-NAME ACTION, and an action-first form, but the three-part form is easiest to read in notes and scripts.
Checkpoint
Write down the version and cluster name before continuing. A host can have several clusters on different ports, and controlling the wrong one is a service outage even when the command succeeds.
2. Check status as the cluster owner
Run status as the owner shown by pg_lsclusters, or as root. This example uses the owner and does not change the server:
$ sudo -u postgres pg_ctlcluster 16 main status
pg_ctl: server is running (PID: 3097710)
/usr/lib/postgresql/16/bin/postgres "-D" "/var/lib/postgresql/16/main" "-c" "config_file=/etc/postgresql/16/main/postgresql.conf"
The PID and command line will differ. Exit status 0 means the server is running. The command returns 2 when it is not running, and 1 for another failure. If you run it as an unrelated unprivileged user, the installed command rejects the request before it can report the cluster state. That is a permissions problem, not proof that PostgreSQL is stopped.
3. Start a stopped cluster
Starting a service changes system state, so first confirm the version, name and intended host. Then run the start action as root or the owner:
$ sudo pg_ctlcluster 16 main start
$ sudo -u postgres pg_ctlcluster 16 main status
pg_ctl: server is running (PID: 12345)
On a successful start, the command exits 0. A start against an already-running cluster exits 2. A normal start creates the cluster log if it does not exist. The default path is /var/log/postgresql/postgresql-16-main.log; check the path printed by pg_lsclusters on your machine if the start fails:
$ sudo tail -n 40 /var/log/postgresql/postgresql-16-main.log
If this is a systemd-managed installation, root invocation is normally redirected to systemctl so the service remains supervised. That is expected behaviour. Do not add --skip-systemctl-redirect merely to make the output look different; the option is intended for the PostgreSQL systemd unit and other specialised cases.
4. Reload configuration without a full restart
Use reload when PostgreSQL supports applying the configuration change without stopping the server:
$ sudo pg_ctlcluster 16 main reload
$ sudo -u postgres pg_ctlcluster 16 main status
pg_ctl: server is running (PID: 12345)
A reload asks PostgreSQL to re-read its configuration. It does not guarantee that every setting can change this way. Check the PostgreSQL log and the relevant setting's documentation when a change appears not to take effect. If the change requires a restart, schedule the interruption and use restart deliberately.
5. Stop or restart with an explicit shutdown mode
Stopping or restarting disconnects clients, so warn users and check the workload first. The default mode is fast: active transactions are rolled back and clients are disconnected so the server can shut down cleanly.
$ sudo pg_ctlcluster --mode fast 16 main stop
$ sudo -u postgres pg_ctlcluster 16 main status
pg_ctl: no server running
For a planned configuration change, a restart performs the same stop and then starts the cluster again:
$ sudo pg_ctlcluster --mode fast 16 main restart
$ sudo -u postgres pg_ctlcluster 16 main status
--mode smart waits for clients to disconnect, while --mode immediate stops without a clean shutdown and can require recovery at the next start. Do not use immediate mode as a routine shortcut. The --force option escalates from fast to immediate and then killing the PostgreSQL process if necessary; the manual says it should only be used when the machine is about to be shut down. It can leave the cluster inconsistent, so treat it as an emergency action.
Recovery is simple after an ordinary stop: run the start command from step 3. If an immediate shutdown was used, allow PostgreSQL to complete recovery and inspect its log before declaring the service healthy.
6. Promote a running standby only with a failover decision
The promote action tells a running standby to leave recovery and begin read-write operation:
$ sudo pg_ctlcluster 16 standby promote
$ sudo -u postgres pg_ctlcluster 16 standby status
Replace standby with the real cluster name. Promotion changes the database role and is not an ordinary health check. Confirm that the failover plan, replication state and application routing are ready before running it. There is no equivalent undo command that turns the promoted server back into the same standby; rebuilding or re-establishing replication is a separate operation.
7. Diagnose the common traps
If an action fails, rerun pg_lsclusters and check the matching log rather than changing ports or paths at random. The manual warns that changing the port at startup with -o -p breaks the checks for running clusters. Use the configured cluster port and make a planned configuration change through PostgreSQL's normal configuration workflow.
Options after -- are passed to pg_ctl. The -o or --options option passes an option to the postgres process, and can be repeated. Keep these advanced options out of routine start and stop commands unless the PostgreSQL documentation and your service configuration require them. Extra PostgreSQL or pg_ctl options also affect the systemd redirect behaviour.
Done means
- You identified the exact version and cluster name with
pg_lsclusters. - Status was checked as the cluster owner or root, with its exit result understood.
- Start and reload were used for their intended, narrower changes.
- Stops and restarts were announced, and the shutdown mode was chosen explicitly.
--forceandimmediatewere reserved for genuine emergencies.- Promotion was treated as a failover operation with no assumed undo.