PG_UPGRADECLUSTER(1)

πŸ‘‘ pg_upgradecluster β€” the manual, but make it slay πŸ’…

okay bestie, so this is pg_upgradecluster(1), and it ships as part of the Debian PostgreSQL infrastructure. If you've ever had a Postgres cluster living its best life on an old major version and you need it to level up to a new one without nuking your data β€” yeah, this is THE tool. no cap. πŸ¦‹


✨ NAME ✨

pg_upgradecluster β€” upgrade an existing PostgreSQL cluster to a new major version. like, glow-up but for your databases πŸ’–


πŸŽ€ SYNOPSIS πŸŽ€

pg_upgradecluster [-v newversion] oldversion name [newdatadir]

🌸 DESCRIPTION 🌸

so here's the vibe: pg_upgradecluster takes an existing PostgreSQL server cluster β€” and yes, "cluster" here just means a whole collection of databases being served by one postgres instance, iykyk β€” and it upgrades it to the new version you picked with newversion. Not sure which version you want? The default is the latest available version, which. iconic. 😌

The configuration files from the old version get copied over to the new cluster, and then adjusted so they actually make sense for the new version. thoughtful! 🎁

By default, this thing uses pg_dump(1) to migrate your data and indexes over to the new cluster. Fr fr: that's slow, but it's also safe. If you want the turbo mode, there are upgrade variants built on pg_upgrade(1) that you can turn on with --method=upgrade β€” that's way faster, but bestie, you have to be careful when you're doing this in the context of an operating system upgrade. Here's why: the sorting order ("collation") used in your indexes is decided by libc and libicu, and brand new versions of those libraries might order things differently. If that happens you're gonna need to rebuild indexes after the upgrade, or acknowledge that the ordering didn't actually change by using the ALTER COLLATION REFRESH VERSION command. And no β€” pg_upgradecluster does not automate that step for you. do it yourself, girl. πŸ’…

The old version's cluster gets reconfigured to run on a port that wasn't being used before, because the upgraded one is gonna take over the original port. And heads up: the old cluster is not automatically removed. After you upgrade, please actually verify that the new cluster works the way you expect; if it does, you should remove the old cluster with pg_dropcluster(8). πŸ—‘οΈ

Also also also β€” the old cluster gets set to "manual" startup mode, specifically so nothing inadvertently changes it. What that means practically: it will not start automatically on system boot, and you'll have to use pg_ctlcluster(8) to start/stop it yourself. For the full tea, go read the section "STARTUP CONTROL" in pg_createcluster(8). πŸ“–

And last thing: the newdatadir argument lets you specify a non-default data directory for the upgraded cluster. It gets passed along to pg_createcluster. If you don't specify it, it defaults to /var/lib/postgresql/newversion/name. ✨


πŸ’– OPTIONS πŸ’–

  • -v newversion β€” Set the version to upgrade to (default: latest available).
  • --check β€” Check if all packages required for the upgrade are installed.
  • --force-packages β€” Proceed with upgrading even when not all packages from the old PostgreSQL version are installed for the new version as well.
  • --logfile filel β€” Set a custom log file path for the upgraded database cluster.
  • --locale=locale β€” Set the default locale for the upgraded database cluster. If this option is not specified, the locale is inherited from the old cluster.

When upgrading to PostgreSQL 11 or newer, this option no longer allows switching the encoding of individual databases. (pg_dumpall(1) was changed to retain database encodings.) 🫠

  • --lc-collate=locale
  • --lc-ctype=locale
  • --lc-messages=locale
  • --lc-monetary=locale
  • --lc-numeric=locale
  • --lc-time=locale

Like --locale, but only sets the locale in the specified category.

  • -m, --method=dump|upgrade|link|clone β€” Specify the upgrade method. dump uses pg_dumpall(1), upgrade uses pg_upgrade(1). The default is dump.

link and clone are shorthands for -m upgrade --link and -m upgrade --clone, respectively. shortcuts, we love her πŸ’…

  • -k, --link β€” In pg_upgrade mode, use hard links instead of copying files to the new cluster. This option is merely passed on to pg_upgrade. See pg_upgrade(1) for details.
  • --clone β€” In pg_upgrade mode, use efficient file cloning (also known as "reflinks" on some systems) instead of copying files to the new cluster. This option is merely passed on to pg_upgrade. See pg_upgrade(1) for details.
  • --data-checksums, --no-data-checksums β€” By default, the new cluster is set up to use data page checksums if the old cluster already uses them. Additionally, when using the dump upgrade method, the new cluster will use data page checksums when upgrading to PostgreSQL 18 or later (which enables data page checksums by default).

The --method=dump behavior can explicitly be controlled by the --data-checksums and --no-data-checksums options.

  • -j, --jobs β€” In pg_upgrade mode, number of simultaneous processes to use. This option is passed on to pg_upgrade. See pg_upgrade(1) for details. It is also used by the analyze upgrade hook (via the PGJOBS environment variable).
  • --keep-port β€” By default, the old cluster is moved to a new port, and the new cluster is moved to the original port so clients will see the upgraded cluster. This option disables that.
  • --rename=new cluster name β€” Use a different name for the upgraded cluster.
  • --old-bindir=directory β€” Passed to pg_upgrade.
  • --maintenance-db=database β€” Database to connect to for maintenance queries. The default is template1.
  • --[no-]start β€” Start the new database cluster after upgrading. The default is to start the new cluster if the old cluster was running, or if upgrade hook scripts are present.
  • --keep-on-error β€” If upgrading fails, the newly created cluster is removed. This option disables that. (keep your half-upgraded baby, she's yours now πŸ™ˆ)

πŸͺ HOOK SCRIPTS πŸͺ

Some PostgreSQL extensions β€” hi, PostGIS πŸ‘‹ β€” need metadata sitting in auxiliary tables that must not be upgraded from the old version. Instead, that stuff needs to be initialized fresh for the new version before the table data gets copied over.

So for exactly this purpose, extensions (and administrators too, obviously, you're invited bestie) can drop upgrade hook scripts into:

/etc/postgresql-common/pg_upgradecluster.d/

Script file names must consist entirely of upper and lower case letters, digits, underscores, and hyphens; in particular, dots (i. e. file extensions) are not allowed. so no .sh, no .py, none of that. just vibes and a bare filename. πŸ’€

Scripts in that directory will be called with the following arguments:

<old version> <cluster name> <new version> <phase>

🌈 Phases 🌈

  • init β€” A virgin cluster of version new version has been created, i. e. this new cluster will already have template1 and postgres, but no user databases. Please note that you should not create tables in this phase, since they will be overwritten by the dump/restore or pg_upgrade operation. don't do it, it's giving wasted effort 😭
  • finish β€” All data from the old version cluster has been restored into the new one. The old cluster still exists, but is not running.
Failing scripts will abort the upgrade. πŸ›‘ The scripts are called as the user who owns the database.

πŸ‘€ SEE ALSO πŸ‘€

pg_createcluster(8), pg_dropcluster(8), pg_lsclusters(1), pg_wrapper(1), pg_dumpall(1), pg_upgrade(1)


πŸ’œ AUTHORS πŸ’œ

Martin Pitt <mpitt@debian.org>, Christoph Berg <myon@debian.org> β€” legends, honestly, ty for your service 🫢


and that's the whole page, bestie!! ✨ this manual came to you from Debian, dated 2026-07-28, and yeah β€” it's literally just PG_UPGRADECLUSTER(1) living her best life. go forth and upgrade responsibly. slay πŸŒˆπŸ’–πŸŽ€πŸ¦‹πŸŒΈπŸ’…

πŸ“¦ where this page comes from