StormaticsStormatics

PostgreSQL 16 Installation on RHEL/CentOS – Step-by-Step Guide

Why Databases? Why PostgreSQL?

In today’s digital world, data is at the heart of every application, from social media platforms to banking systems, from e-commerce websites to IoT devices. To manage this data efficiently, reliably, and securely, we need a robust system known as a database management system (DBMS). Among the many DBMS options available, PostgreSQL stands out as a top choice for developers and enterprises alike. 

Here’s why PostgreSQL is a go-to database for modern applications:

  • Standards-compliant and ACID-compliant for strong reliability
  • Supports both relational and non-relational data (via JSON, hstore)
  • Extensible because you can create your own data types, operators, and functions. Advanced indexing and full-text search capabilities
  • Runs on all major OS platforms and integrates well with cloud environments

While PostgreSQL 17 is the latest version, this guide focuses on PostgreSQL 16. In many production environments, it’s common to work with the n-1 version for stability and upgrade planning.

PostgreSQL follows a major.minor versioning scheme. Major versions (e.g., 15, 16) introduce significant new features and improvements, while minor versions (e.g., 16.1, 16.2, 16.3) focus on bug fixes, security patches, and stability enhancements without changing the database’s behavior or internal structures.

Key Differences Between Major and Minor Versions:

  • Major versions are released once a year and may include new features and improvements with bug-fixes.
  • Minor versions are typically released every three months. However, in the event of critical security or stability issues, a release may occur sooner to address the problem promptly. 

These features were introduced in PostgreSQL 16 and are fully available in PostgreSQL 17 as well, along with additional enhancements. 

  • Performance Improvements: Enhanced parallel query performance, faster sorting, and better write-ahead logging efficiency.
  • SQL/JSON Enhancements: Improved support for SQL/JSON syntax and operations, aligning more closely with SQL standards.
  • Better Logical Replication: More granular control over replication slots, publication filters, and conflict handling.
  • Improved Monitoring: New pg_stat_io view and better statistics for vacuum operations.

By installing PostgreSQL 16.3, you are  gaining access to the most recent improvements while ensuring long-term compatibility and security. It’s the ideal choice for teams looking to leverage modern database features without sacrificing reliability.

This blog provides a step-by-step guide to installing PostgreSQL 16.3 on a Red Hat Enterprise Linux 9 (RHEL 9) system. The latest version introduces performance enhancements, expanded SQL/JSON features, and improved logical replication, making it a compelling choice for both developers and data professionals.

Prerequisites

Before installing PostgreSQL, it’s important to prepare your system to avoid any issues during or after installation. First, make sure your operating system is up to date by running the system update command

 sudo yum update -y 

(used for older versions like RHEL 7, CentOS7)

                           or 

 sudo dnf update -y 

(used for newer versions like RHEL 8, RHEL 9, Fedora)

This ensures that all packages and security updates are current. You will also need administrative (root or sudo) access to install software and make configuration changes. Before installing PostgreSQL, it’s important to know which OS version and architecture you’re working on. This ensures that you download the correct repository package.

To begin the PostgreSQL installation, log in to the server where you want to install the database. You’ll need to have administrative access, so after logging in, switch to the root user using the command sudo su – root. This ensures you have the necessary permissions to install software and make system-level changes. Before proceeding with the installation.

cat /etc/redhat-release
uname -m

It’s important to verify if your server has enough disk space. You can do this by running the command df -Ph, which displays the available and used disk space on all mounted file systems in a human-readable format. 

While PostgreSQL itself is lightweight and requires less than 50 MB for installation, the real disk space considerations come from your data usage. The bulk of storage is consumed by the database files, write-ahead logs (WAL), temporary query files, and backups. Therefore, even though the initial install takes up very little space, it’s important to ensure that the partition where PostgreSQL’s data directory resides.Disk space requirements will vary based on factors like the size of your datasets, write activity, and backup strategy. Always plan ahead and monitor disk usage regularly, especially in production environments, to avoid performance issues or downtime.

1. Download and Install PostgreSQL

To download and install PostgreSQL on a RHEL-based system like Red Hat Enterprise Linux, CentOS, or Oracle Linux, you should start by visiting the official PostgreSQL Linux downloads page: https://www.postgresql.org/download/linux/redhat/.

Choose the PostgreSQL version you want to install

In the “Select version” dropdown, choose 16(You can select other versions like 15, 16, 17 depending on your requirement)

 Choose the platform

In the “Select platform” dropdown, select: Red Hat Enterprise, CentOS, Scientific or Oracle version 10(This depends on your OS – for example, CentOS 10)

 Select system architecture: Choose: x86_64 (This is the most common 64-bit option for servers)

Copy the script generated below

After selecting the above options, a setup script will appear.

Copy that script as it contains all the necessary commands for your environment.

2. Add PostgreSQL YUM Repository

 A YUM repo is a collection of software packages that your Linux system can download and install using yum or dnf. PostgreSQL provides its own YUM repo where it maintains current versions (like 12, 13, 14, 15, 16) for different OS versions and architectures.

We want to install PostgreSQL 16 (or any newer version) on a Red Hat-based Linux system such as:

  • RHEL (Red Hat Enterprise Linux), CentOS, Rocky Linux, AlmaLinux

However, the default system repository (the place your OS checks for software) may not include the latest PostgreSQL version or it might only provide an outdated one, like PostgreSQL 9 or 10. So we need to tell the system where to find official PostgreSQL 16 packages by adding PostgreSQL’s YUM repository to your system.

Download the official PostgreSQL repository.

For RHEL/CentOS 7:

sudo yum install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm

For RHEL/CentOS 8 or newer:

sudo dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-8-x86_64/pgdg-redhat-repo-latest.noarch.rpm

Once you run the right command for your system, your computer will know where to look when you ask it to install PostgreSQL 16 later. This step is very important if you skip it, your system won’t find the latest version of PostgreSQL.

3. Disable the Default PostgreSQL Module (For RHEL 8+)

If you’re using RHEL 8, CentOS 8, or any newer Red Hat-based system, your operating system comes with a built-in module for PostgreSQL. This module usually includes an older version, like PostgreSQL 10 or 12, not the latest one that you want to install.

To avoid your system installing the older version by mistake, you need to turn off (disable) that default module first. This step ensures your system won’t get confused and will only use the PostgreSQL version provided by the new official repository you added in the previous step. You can do this by running the following command:

 sudo dnf -qy module disable postgresql

After this step, your system is ready to install PostgreSQL 16 from the official PostgreSQL repo instead of installing an outdated version from the system’s default source.

4. Refresh Local Repository cache:

sudo dnf clean all

The sudo dnf clean all command is used to clear all cached data used by the DNF package manager on RHEL-based systems. This includes metadata, downloaded RPM packages, and repository information stored locally on the system. It is particularly useful when the cached data becomes outdated or corrupted, as it forces the system to discard any previously stored information and start fresh. This helps avoid installation or update issues that can occur due to stale or mismatched metadata and ensures that future package operations pull the most current information from remote repositories.

sudo dnf makecache

Following that, sudo dnf makecache regenerates the local cache by downloading the latest metadata from all enabled repositories. This command improves the speed and reliability of future dnf commands by ensuring that the system has up-to-date knowledge of available packages. It’s especially important after adding a new repository (like the PostgreSQL YUM repo) or after cleaning the cache, as it preloads the data required to perform installations or searches. Together, these two commands help maintain a clean and efficient package management environment.

5. Install PostgreSQL 16 Packages

Use the appropriate command depending on your system:

For RHEL 7:

Sudo yum install -y postgresql16-16.3 postgresql16-server-16.3 postgresql16-contrib-16.3 

For RHEL 8+:

sudo dnf install -y postgresql16-16.3 postgresql16-server-16.3 postgresql16-contrib-16.3

The command explicitly installs four essential packages for PostgreSQL.

  • postgresql16.3 installs the core client utilities such as psql, which are used for connecting to and administering the database. 
  • postgresql16.3-server brings in the main database server responsible for handling data storage, transaction processing, and queries. 
  • postgresql16.3-contrib provides a set of useful extensions that aren’t part of the core database engine but enhance its capabilities. For example, pg_stat_statements is valuable for performance monitoring and query analysis.

Installing these packages explicitly by version is critical in production environments. It ensures you’re installing a known, tested version rather than the latest one that might introduce unverified changes or regressions. This version of pinning supports repeatable deployments, easier debugging, cross-environment consistency, and more stable integration with existing systems and applications.

6. Configure Custom Data Directory (Recommended in Production)

The next step is to initialize the database cluster, which involves creating the necessary file structure for PostgreSQL to store data. By default, PostgreSQL creates this under:

/var/lib/pgsql/16/data

However, in production environments, storing critical database data on the root (/) partition is discouraged. It can lead to space-related failures that affect the entire system. To mitigate this, it’s recommended to use a dedicated disk mount point, ensuring better isolation, scalability, and disaster recovery planning.

In the below example I am using /pgdata/pg16. For production environments, it’s strongly recommended to mount a dedicated disk or volume to /pgdata. This ensures PostgreSQL data is stored separately from the root partition, improving performance, scalability, and system stability.

7. Set the Custom Data Directory in the Systemd Service File

Before initializing the database, we need to tell systemd (the Linux service manager) to use our desired custom location for PostgreSQL data.

Open the PostgreSQL 16 systemd service file:

sudo vi /usr/lib/systemd/system/postgresql-16.service

Find or add the Environment directive under the [Service] section:

Environment=PGDATA=/pgdata/pg16

This instructs PostgreSQL to search for its data cluster in the custom directory instead of the default one.

Reload systemd to apply the changes:

sudo systemctl daemon-reload

This step is critical. It updates systemd with your modified service configuration. Without it, your changes won’t take effect when you start the PostgreSQL service.

8. Initialize the Database

After configuring systemd to recognize a non-default PostgreSQL data directory (in the previous step), the next task is to actually create and initialize that directory so PostgreSQL can start using it.

Create the Custom Data Directory

sudo mkdir -p /pgdata/pg16

This command creates the new directory /pgdata/pg16 where PostgreSQL will store all of its internal files, configuration, transaction logs, system catalogs, and user data. The -p option ensures that the full path is created even if intermediate directories (/pgdata) do not exist.

  • Using a separate mount point like /pgdata is a common production practice because it:
  • Prevents the root (/) partition from filling up and potentially crashing the server.
  • Allows for better I/O performance if placed on SSDs or dedicated volumes.
  • Helps with backup, restore, and disaster recovery processes by isolating database files from system files

Assign Correct Permissions

sudo chown -R postgres:postgres /pgdata/pg16

This changes the ownership of the directory and its contents to the postgres user and group. PostgreSQL services always run under the postgres system user, and the database will fail to start if it cannot write to the data directory. This step ensures PostgreSQL can read, write, and manage files in the new directory.

Switch to the postgres User

sudo su - postgres

PostgreSQL administrative tools like initdb must be run as the postgres user for security and permission reasons. This command logs you into a shell session as the postgres user so you can safely initialize the database environment.

Initialize the Data Directory

/usr/pgsql-16/bin/initdb -D /pgdata/pg16 --data-checksums

This command initializes the PostgreSQL database cluster inside your specified directory (/pgdata/pg16).

The -D flag points to the custom data directory.

The –data-checksums option enables checksums for each data page. This helps detect silent data corruption due to disk or memory errors. While enabling checksums adds a small performance overhead, it significantly improves reliability and data integrity  a critical aspect in production systems.

The initdb process creates essential files such as:

  • postgresql.conf: the main configuration file for server behavior.
  • pg_hba.conf: controls client authentication.
  • Physical subdirectories for base tables, WAL (Write Ahead Logs), and transaction logs.

This step only needs to be done once, right after installing PostgreSQL and before starting the service. After successful initialization, the system is ready to start accepting connections once the PostgreSQL service is started.

9. Enable and Start PostgreSQL Service

Now that PostgreSQL has been installed and initialized, the next step is to make sure the database service is always available when the system restarts. First, we use the enable command. Go to root user and give

systemctl enable postgresql-16

This tells the operating system to automatically start the PostgreSQL 16 service every time the server boots up. Without this, PostgreSQL would remain stopped after a reboot unless manually started. Next, we start the PostgreSQL service right away with:

systemctl start postgresql-16

This command launches the PostgreSQL server immediately, making it ready to accept connections and handle databases. Once the service starts successfully, PostgreSQL is running in the background and ready for use.

10. Verify PostgreSQL Status

After starting the PostgreSQL service, it’s a good practice to confirm that everything is running as expected. To check the status of the PostgreSQL 16 service, use the following command:

systemctl status postgresql-16

This command shows whether the service is active, inactive, or has encountered any errors. If everything is working correctly, you will see a message like “active (running)” along with the process ID and startup time. This status output helps you verify that the server has successfully started and is now ready to accept connections.

If the status shows “failed” or “inactive,” it means something went wrong, and you may need to review the logs to troubleshoot the issue. However, if it’s running, you’re good to proceed to the following steps, such as creating users and databases.

Post-Installation Setup

Now that the PostgreSQL server is running, you can connect to it and begin working with databases. PostgreSQL creates a default administrative user called postgres during installation. This user has full access to the database system and is used for initial setup and management.

sudo su – postgres

This command logs you into the postgres user account, allowing you to perform administrative tasks inside PostgreSQL. Next, to open the PostgreSQL command-line interface, run:

psql

This will launch the interactive terminal for PostgreSQL. If successful, you will see a prompt that looks like this:

You should now see the postgres=# prompt.

Troubleshooting Installation Issues 

Installing PostgreSQL on RHEL 9 is generally straightforward, but certain issues may arise due to repository configuration, package cache, or conflicting system modules. Below are the most common installation problems and how to resolve them.

1. “Unable to find a match” or Package Not Found

Error:

Unable to find a match: postgresql16 postgresql16-server ...

Cause: The PostgreSQL repository was not added properly, or the package cache is outdated.

How to Fix it:

Add the official PostgreSQL repository for RHEL 9

sudo dnf install -y 
https://download.postgresql.org/pub/repos/yum/reporpms/EL-9-x86_64/pgdg-redhat-repo-latest.noarch.rpm

Then, clean and refresh the DNF cache:

sudo dnf clean all
sudo dnf makecache

2. Conflicts with the Default PostgreSQL Module

Error:

The operation would result in switching of module ...

Cause: RHEL comes with its own version of PostgreSQL enabled as a system module, which can conflict with the one from the official PostgreSQL repository.

How to Fix it:

Disable the system module before installing PostgreSQL 16:

sudo dnf -qy module disable postgresql

3. Wrong Repository Version Used

Error:

 No package postgresql16 available.

Cause: You may be using a repository built for the wrong version of RHEL (e.g., EL-8 instead of EL-9).

How to fix it

Ensure you’re using the correct repository for EL-9:

https://download.postgresql.org/pub/repos/yum/reporpms/EL-9-x86_64/pgdg-redhat-repo-latest.noarch.rpm

Reinstall the correct repo if needed:

sudo dnf remove pgdg-redhat-repo
sudo dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-9-x86_64/pgdg-redhat-repo-latest.noarch.rpm

Uninstalling or Rolling Back PostgreSQL Installation

Sometimes you may need to remove PostgreSQL from your system maybe to fix issues, switch to a different version, or clean up the setup. Here’s how you can safely uninstall PostgreSQL 16:

1. Stop the PostgreSQL Service

Before uninstalling PostgreSQL, it’s important to stop the service to ensure that the database isn’t running during the removal process. This prevents any potential issues or conflicts. You can stop the PostgreSQL 16 service by running the command:

sudo systemctl stop postgresql-16

This tells the system to immediately shut down the PostgreSQL server safely.

2. Disable the Service from Starting Automatically

After stopping the PostgreSQL service, the next step is to disable it so that it doesn’t start automatically the next time the system boots. This is especially useful if you’re planning to remove PostgreSQL completely or switch to a different version. To do this, run the command

sudo systemctl disable postgresql-16

This removes PostgreSQL 16 from the list of services that start at boot time.

3. Remove PostgreSQL 16.3 Packages

Once the PostgreSQL service is stopped and disabled, the next step is to remove the PostgreSQL software from your system. This includes the database server, client tools, libraries, and any related extensions. The command you use depends on your Linux version. 

CentOS 7:

sudo yum remove postgresql163*

CentOS/RHEL 8 or 9:

sudo dnf remove postgresql163*

4. Delete the Data Folder (Optional)

This step is optional and should only be done if you’re sure you don’t need any of your old PostgreSQL databases. The data directory is where all your database files are stored. If you want to completely remove PostgreSQL and start fresh in the future, you can delete this directory using:

sudo rm -rf /pgdata/pg16

If you used the default location:

sudo rm -rf /var/lib/pgsql/16/data

Be very careful as this command permanently deletes all database data and cannot be undone.

5. Remove the PostgreSQL Repository (Optional)

This optional step is for cleaning your system. If you added the PostgreSQL YUM repository during installation and no longer need it, remove it with ‘sudo yum remove pgdg-redhat-repo’ (YUM systems) or ‘sudo dnf remove pgdg-redhat-repo’ (DNF systems). This deletes the PostgreSQL repository reference.

Conclusion

In this guide, we explored the importance of databases in modern applications and why PostgreSQL remains a top choice for developers and enterprises alike. We provided a detailed walkthrough of installing PostgreSQL 16.3 on RHEL 9, including repository configuration, dependency management, and essential post-installation steps. We also addressed common installation issues and offered practical troubleshooting tips to ensure a smooth setup experience.

Keeping PostgreSQL up to date is essential not only for accessing the latest features and performance improvements but also for maintaining security and long-term stability. Minor releases like 16.3 often include critical patches that protect against known vulnerabilities and optimize database behavior under heavy workloads.

As next steps, you may consider:

  • Installing a graphical interface such as pgAdmin for easier database management.
  • Configuring automated backups using tools like pg_dump or pgBackRest.
  • Setting up replication for high availability and disaster recovery.
  • Exploring role-based access control, monitoring tools, and performance tuning

With PostgreSQL 16.3 successfully installed, you’re now equipped to build scalable, secure, and feature-rich applications. Stay tuned for our upcoming blog on PostgreSQL user management and advanced configuration.

Leave A Comment