Home / Alt manpages / pg_createcluster(1)

  • pg_createcluster(1)
  • User command
  • linux

Create a Second PostgreSQL Cluster with pg_createcluster

pg_createcluster spins up a complete second PostgreSQL server instance alongside your existing one, on its own port and in its own directories. This walkthrough creates a cluster called reporting, verifies its files and status, then removes it cleanly once the test is over.

This uses pg_createcluster from postgresql-common, installed here as version 257build1.1, with PostgreSQL 16. Allow about fifteen minutes. You need a PostgreSQL server package, a shell, and sudo access.

A cluster is a full PostgreSQL server instance, not merely another database. Creating one writes data under /var/lib/postgresql, configuration under /etc/postgresql, and a log under /var/log/postgresql. The examples change system state, so read each warning before running a command.

1. Check the installed version and existing clusters

These are ordinary read-only commands. Do not choose a version that is not installed, and do not reuse an existing cluster name for that version.

$ dpkg-query -W -f='${Package} ${Version}\n' postgresql-common postgresql-16
postgresql-common 257build1.1
postgresql-16 16.15-0ubuntu0.24.04.1
$ command -v pg_createcluster
/usr/bin/pg_createcluster
$ 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

Your list will differ. In the rest of this guide, 16 is the major version and reporting is a new name. Cluster names should not contain dashes, because systemd integration warns about them.

2. Choose an isolated port and startup policy

  • Default port is the next free port starting at 5432. For a second cluster, an explicit port keeps connection strings and checks unambiguous. The example uses 55432; pick another unprivileged port if it is already taken.
  • Default startup policy is auto, meaning the cluster is managed with the PostgreSQL service and may start on boot. The command below selects manual instead, which is a safer first state for a test cluster.

Checkpoint

Confirm the port is unused before creating anything:

$ ss -ltn | awk '$4 ~ /:55432$/ {print}'
$ pg_lsclusters

No output from the first command is the expected result. If another service owns the port, stop and pick a different one. Do not use /tmp as the socket directory for a real cluster: the manpage warns that anybody can create a socket there and impersonate the server.

3. Create the cluster without starting it

This is the state-changing step and needs elevated privileges. It creates a new data directory and configuration set. The authentication options go after --, passed through to initdb. Supplying both local and host authentication methods avoids the documented trap where specifying only one can leave the other as trust.

$ sudo pg_createcluster --start-conf=manual --port=55432 16 reporting -- \
    --auth-local=peer --auth-host=scram-sha-256

Without --datadir, the data directory is /var/lib/postgresql/16/reporting. Without --logfile, the log is /var/log/postgresql/postgresql-16-reporting.log. The configuration directory is /etc/postgresql/16/reporting. The command also picks the default database superuser, postgres, unless you supply --user with a non-root account.

Warning

Do not add --start to this first run. Starting a database is a separate operational decision, and the resulting service can accept connections before you have checked its authentication and port settings.

4. Verify the files and status

Check the result before starting the server:

$ 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
16  reporting  55432 down   postgres /var/lib/postgresql/16/reporting  /var/log/postgresql/postgresql-16-reporting.log
$ sudo grep -E '^(port|data_directory|listen_addresses)' /etc/postgresql/16/reporting/postgresql.conf
port = 55432
$ sudo cat /etc/postgresql/16/reporting/start.conf
manual

The exact spacing and other configuration lines can vary. The useful checks are the new cluster name, port, down status, and manual startup policy. A failed creation may leave partial files; do not guess what is safe to reuse. Inspect the error, then remove the incomplete cluster with the cleanup command in step 6 if it still shows up in pg_lsclusters.

5. Start and stop it deliberately

Starting the cluster is service-disrupting only for this new instance, but it still makes a database available to clients. Confirm the port and authentication configuration first, then run the elevated command:

$ sudo pg_ctlcluster 16 reporting start
$ 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
16  reporting  55432 online postgres /var/lib/postgresql/16/reporting  /var/log/postgresql/postgresql-16-reporting.log

When you finish testing, stop this cluster explicitly. A normal stop uses PostgreSQL's fast shutdown mode:

$ sudo pg_ctlcluster 16 reporting stop
$ pg_lsclusters | grep -E '^16[[:space:]]+reporting[[:space:]]'
16  reporting  55432 down   postgres /var/lib/postgresql/16/reporting /var/log/postgresql/postgresql-16-reporting.log

Do not use pg_ctlcluster --force as routine recovery. Its documented escalation can move to immediate shutdown and then kill the process, which can leave recovery work for the next start.

6. Remove a disposable test cluster

Warning

This is irreversible. pg_dropcluster deletes the cluster's data, WAL and tablespace directories, log, and configuration files. Make sure the name and version identify the disposable cluster, not main or a production instance.

$ pg_lsclusters
$ sudo pg_dropcluster --stop 16 reporting
$ pg_lsclusters

The --stop option makes cleanup proceed even if the test server is still running. If you need to keep the data, stop and back it up instead; do not run this command. A successful final listing no longer contains 16 reporting.

Common traps

  • Cluster names are only unique within a major version. Check both columns in pg_lsclusters.
  • An available port is not a security boundary. Review listen_addresses before opening remote access.
  • start.conf controls Debian's integration, not every possible low-level way to launch postgres. Treat disabled as an accident barrier, not a complete security boundary.
  • Editing start.conf on a systemd host needs a follow-up sudo systemctl daemon-reload. Choosing manual during creation avoids that edit entirely.

Done means

  • Version installed and name unused for the requested PostgreSQL major version.
  • Cluster created on a checked port with both authentication methods set.
  • pg_lsclusters confirms owner, data directory, port and status.
  • Server started and stopped deliberately, not enabled accidentally at boot.
  • Any disposable cluster removed only after its data was confirmed expendable.