When I started working on my pet project to scratch an itch I had (and still have), the newest PostgreSQL version was 14. I picked it with a full confidence that it will serve me for a long time - and it did. Recently, however, I started stumbling upon posts extolling upcoming PostgreSQL 17 more and more often, which made me feel like I’m lagging behind.
To be honest, there’s is no pressing need for me to upgrade - PostgreSQL 14 serves me just fine, and would most likely continue to do so indefinitely. It’s actually already a huge overkill, since I do not really have a lot of requirements that could only be fulfilled by a top-class relational database. However, I do like my tools fresh and sharp, even if they’re way too sophisticated for the job, so I decided to upgrade either way.
TL;DR
For those in the rush, here’s the outline of the whole upgrade procedure I did:
Background
If you take a few moments to research how to upgrade a PostgreSQL version, you’ll find that there are at least a few ways to do it [1]. Some are safer than others, some are easier but riskier. To evaluate which fit me the best, I had a few simple requirements in my mind:
- I want it to be uncomplicated (I can afford downtime if it makes things easier)
- I don’t want to lose any data (though I can deal with it if it happens)
To be perfectly honest, if you’re fine with downtime and okay with risking your data (either because you don’t care or, in my case, you have a backup and don’t mind restoring data in the worst case scenario), you can basically wing the upgrade anyway way you like. With that in mind, I chose the simplest approach I could find: using pg_upgradecluster
which comes from a postgresql-common
package containing a bunch of tools to maintain and manage your PostgreSQL installation(s).
Note, though, that I have not tried this method on a cluster that’s under serious production load, with hundreds of gigabytes of data, leader-follower setup and all the other fancy bells and whistles. In my case, my database is just a few tables with a small amount of data and no special extensions and/or customizations. Thus, if you have something more serious, I would advise to triple check whether this procedure would fit your needs.
With that in mind, let’s see how the process of upgrade from PostgreSQL 14 to 16 looks like.
Specs
To start of, I began from the following state.
Ubuntu version:
PostgreSQL version:
For reference, database size was a measly 11 MB - practically nothing compared to even moderately sized production databases.
Steps
postgresql
Installing First of all, I had to install postgresql-common
tools, which automatically configures the necessary repository [2]:
This allowed me to install postgresql
:
Without the postgresql-common
installation and setup, I was getting a bunch of errors that various PostgreSQL-related packages could not be found.
Upgrading PostgreSQL clusters
postgresql
installation should create and start a new PostgreSQL cluster. You can do a sanity check to verify that you now have two clusters running [3]: one for the old PostgreSQL version (14), and one for the new one (16).
Note that “cluster” in this case has nothing to do with the common definition of a group of servers working together to achieve higher performance on some task. In PostgreSQL world, it’s defined as:
A database cluster is a collection of databases that is managed by a single instance of a running database server. […] In file system terms, a database cluster is a single directory under which all data will be stored. [4]
Turning to the output above, notice that the new cluster (16) is running on port 5433
. Thus, if you have some apps that are connected to the database on port 5432
, they’ll still be using the old version. This is expected for now as we have not performed an upgrade yet.
Once PostgreSQL 16 is installed, we can begin moving our old server to the new PostgreSQL version. First of all, we need to drop the new cluster (16) [5], since we’ll be upgrading our old cluster (14) to a newer version:
We include --stop
flag to force a server shutdown before files are removed, as normally a cluster which has a running server will not be deleted.
Once we’ve dropped the cluster with the new PostgreSQL version (16), we can go for the meat of the upgrade: pg_upgradecluster
[6]:
With this, we can see that our database version has been upgraded to 16. Last few lines detail that now we have a PostgreSQL 16 cluster listening on port 5432
(default PostgreSQL port) which used to be occupied by PostgreSQL 14 cluster. The latter is now listening on 5433
- or would be, if it wasn’t down
.
The next steps are sanity checks to see if all works well, if our apps can talk to PostgreSQL. If nothing seems amiss, we can drop the old (14) cluster:
And verify that we don’t have it anymore:
Clean Up
Now that we’ve upgraded the database, there’s no need to keep the old version around, so we might as well delete it:
And with that, we’ve concluded the upgrade.
Summary
To be perfectly honest, I expected the upgrade to be much more involved, which is why I postponed it in multiple times. In the end, though, it turned out surprisingly easy - at least for my trivial, uncomplicated database setup.
Sources
- https://www.postgresql.org/docs/current/upgrading.html
- https://www.postgresql.org/download/linux/ubuntu/
- https://manpages.ubuntu.com/manpages/xenial/en/man1/pg_lsclusters.1.html
- https://www.postgresql.org/docs/current/creating-cluster.html#CREATING-CLUSTER
- https://manpages.ubuntu.com/manpages/trusty/man8/pg_dropcluster.8.html
- https://manpages.ubuntu.com/manpages/trusty/man8/pg_upgradecluster.8.html