During the course of your software development career, you get to use different flavors and versions of databases, such as PostgreSQL. Newer projects and applications often use the latest versions while older projects tend to lag behind in upgrading their stack.
Consequently you need to be able to run different versions of the database in your machine, and be able to switch easily between versions. The alternatives, such as re-installing the desired version when needed or using a different machine for different projects, isn’t practical most of the time.
In macOS, you can easily run multiple versions of PostgreSQL using Homebrew or PostgresApp. If you are using Linux, there is a great tool that you can use to achieve this called pgenv.
If you are familiar with libraries such as rbenv, then you are already familiar as to how it works. Just like running multiple versions of Ruby using rbenv, you can run multiple PostgreSQL versions using pgenv.
Like rbenv, pgenv installs the different database versions separately from the system installation, with data and binaries that are compartmentalized inside the user’s home directory. These types of libraries provide simple but effective solutions when running multiple versions of software. As the files are kept separate from the database installed in the system, it is easy to add and remove versions of PostgreSQL as well.
Installation
Like other software management libraries, installing pgenv is straightforward.
First, download the library source code to your machine:
git clone https://github.com/theory/pgenv.git ~/.pgenv
Add the pgenv binaries to PATH:
echo 'export PATH="$HOME/.pgenv/bin:$HOME/.pgenv/pgsql/bin:$PATH"' >> ~/.profile
Reload your shell so that the PATH changes will take effect. Once that is done, you can start using the pgenv command to install a specific version of PostgreSQL:
pgenv build 13.9
Common Commands
pgenv build <version>
This downloads and builds the specified PostgreSQL version. Running this command again does not rebuild the version (see clear).
pgenv remove <version>
Deletes the specified version from your machine. Note that you cannot remove currently-used versions, so you need to use the clear command first if you intend to do that.
pgenv use <version>
Sets the current version of PostgreSQL to use, and then runs that version.
pgenv stop
Stops the current (running) version of the database.
pgenv clear
Unsets the current version of the database. If that version is running, then this command will stop it first, before unsetting it. This command is used if you want to rebuild a specific version (if it is the version currently used).
pgenv rebuild <version>
Rebuilds a version of PostgreSQL from source. This is used if you want to add extensions, as these are added during the build phase.
PostgreSQL Extensions
If your application requires PostgreSQL extensions (which is very likely), then these should be configured during the build phase.
One popular extension is PostGIS, which needs to be compiled and installed from source to work with pgenv. Here are the steps to compile and install PostGIS.
Installing dependencies (proj, protobuf, gdal, geos)
sudo apt install libproj-dev
sudo apt install protobuf-c-compiler libjsoncpp-dev libprotobuf-dev libprotobuf-c-dev libxml2-dev
sudo apt install libgdal-dev
sudo apt install libgeos++-dev libgeos-c1v5 libgeos-dev libgeos-doc
Install the PostGIS scripts library
sudo apt install postgresql-13-postgis-3-scripts
Download the PostGIS source code
wget https://download.osgeo.org/postgis/source/postgis-3.3.2.tar.gz
Extract and build from source
tar xvzf postgis-3.3.2.tar.gz
cd postgis-3.3.2
eval ./configure $(pg_config --configure)/
make
make install
Adding PostgreSQL build flags
When building a PostgreSQL version, there are times when we need to set flags during the build/compile step. For example, your application may require the OpenSSL extension for PostgreSQL, which is not included by default when building through pgenv.
This results in an error that is similar to the following:
PG::UndefinedFile: ERROR: could not open extension control file "/home/user/.pgenv/pgsql-13.8/share/extension/sslinfo.control": No such file or directory
The library provides a config edit command that allows you to customize the build configuration, setting the default user, and even initdb options. You can edit the config file using your favorite editor by adding it as an environment variable:
% EDITOR=nano pgenv config edit 13.8
After the configuration file is loaded in the editor, you can now change various flags to customize pgenv. It comes with comments to point how to use each configuration. In our case, we want to compile the database with OpenSSL, so we add it to the build config, which is PGENV_CONFIGURE_OPTIONS.
# Configure flags, including PL languages but without --prefix
PGENV_CONFIGURE_OPTIONS=(--with-openssl)
export PGENV_CONFIGURE_OPTIONS
After updating the config file, we need to rebuild PostgreSQL so that the changes can take effect.
First, the version that is currently set needs to be stopped first and also be “unset” as the current version. pgenv provides the clear command to do both:
% pgenv clear 13.9
PostgreSQL 13.9 stopped
Then once the database is stopped, we can rebuild it again, this time with the configuration changes applied:
% pgenv rebuild 13.9
After the PostgreSQL version has been reinstalled, you can run it again using this command:
% pgenv use 13.9