How to Use pg_controldata to Inspect Your PostgreSQL Database Cluster

Pg_controldata is a utility tool in postgres that we can use to read the contents from the pg_control file. When we install postgresql, a default cluster is created. During the creation of a cluster, it creates a pg_control file that contains the metadata related to the postgresql cluster.

Now, lets check the actual path of pg_control data inside /usr folder through the find command.

find /usr -name pg_controldata 2>/dev/null
  • find - This is the command we used to search this file.
  • /usr - searching the file inside this directory
  • -name - searching the file or directory based on the exact name pg_controldata
  • 2>/dev/null - redirect the error message occured during this process to the path dev/null

Result :

/usr/local/pgsql/bin/pg_controldata
/usr/lib/postgresql/14/bin/pg_controldata
/usr/lib/postgresql/18/bin/pg_controldata
/usr/lib/postgresql/17/bin/pg_controldata

Use the help command with the pg_controldata like this.

/usr/lib/postgresql/18/bin/pg_controldata --help

Result :

pg_controldata displays control information of a PostgreSQL database cluster.
Usage:
  pg_controldata [OPTION] [DATADIR]
Options:
 [-D, --pgdata=]DATADIR  data directory
  -V, --version          output version information, then exit
  -?, --help             show this help, then exit
If no data directory (DATADIR) is specified, the environment variable PGDATA
is used.
Report bugs to <pgsql-bugs@lists.postgresql.org>.
PostgreSQL home page: <https://www.postgresql.org/>

Check the version of the pg_controldata utility like this.

/usr/lib/postgresql/18/bin/pg_controldata -V

Result :

pg_controldata (PostgreSQL) 18.4 (Ubuntu 18.4-1.pgdg22.04+1)

Can you also use the -? Instead of the help command.

/usr/lib/postgresql/18/bin/pg_controldata -?

Result :

pg_controldata displays control information of a PostgreSQL database cluster.
Usage:
  pg_controldata [OPTION] [DATADIR]
Options:
 [-D, --pgdata=]DATADIR  data directory
  -V, --version          output version information, then exit
  -?, --help             show this help, then exit
If no data directory (DATADIR) is specified, the environment variable PGDATA
is used.
Report bugs to <pgsql-bugs@lists.postgresql.org>.
PostgreSQL home page: <https://www.postgresql.org/>

Check the data directory.

show data_directory;

Result :

       data_directory        
-----------------------------
 /var/lib/postgresql/18/main
(1 row)

Now, use the data directory with the pg_controldata utility as follows.

/usr/lib/postgresql/18/bin/pg_controldata -D /var/lib/postgresql/18/main

Result :

pg_control version number:            1800
Catalog version number:               202506291
Database system identifier:           7658634883587915935
Database cluster state:               in production
pg_control last modified:             Saturday 01 August 2026 09:50:51 AM
Latest checkpoint location:           17/DF691F20
Latest checkpoint's REDO location:    17/DF691EC8
Latest checkpoint's REDO WAL file:    0000000100000017000000DF
Latest checkpoint's TimeLineID:       1
Latest checkpoint's PrevTimeLineID:   1
Latest checkpoint's full_page_writes: on
Latest checkpoint's NextXID:          0:33775
Latest checkpoint's NextOID:          199126
Latest checkpoint's NextMultiXactId:  1643
Latest checkpoint's NextMultiOffset:  3445
Latest checkpoint's oldestXID:        744
Latest checkpoint's oldestXID's DB:   1
Latest checkpoint's oldestActiveXID:  33775
Latest checkpoint's oldestMultiXid:   1
Latest checkpoint's oldestMulti's DB: 1
Latest checkpoint's oldestCommitTsXid:0
Latest checkpoint's newestCommitTsXid:0
Time of latest checkpoint:            Saturday 01 August 2026 09:50:51 AM
Fake LSN counter for unlogged rels:   0/3E8
Minimum recovery ending location:     0/0
Min recovery ending loc's timeline:   0
Backup start location:                0/0
Backup end location:                  0/0
End-of-backup record required:        no
wal_level setting:                    replica
wal_log_hints setting:                off
max_connections setting:              100
max_worker_processes setting:         8
max_wal_senders setting:              10
max_prepared_xacts setting:           0
max_locks_per_xact setting:           64
track_commit_timestamp setting:       off
Maximum data alignment:               8
Database block size:                  8192
Blocks per segment of large relation: 131072
WAL block size:                       8192
Bytes per WAL segment:                16777216
Maximum length of identifiers:        64
Maximum columns in an index:          32
Maximum size of a TOAST chunk:        1996
Size of a large-object chunk:         2048
Date/time type storage:               64-bit integers
Float8 argument passing:              by value
Data page checksum version:           1
Default char data signedness:         signed
Mock authentication nonce:            1e136b0360ba64f47f8ed7a31ff12984be507300654f384594c6207354f91da5

The output of pg_controldata gives us a lot of information about the state of a PostgreSQL database cluster. It reads all the values from the pg_control file. PostgreSQL updates this file automatically when the server is running. This information is really useful when we want to check if the cluster is healthy, if the configuration settings are correct, if we are having problems with recovery, or if we want to confirm that the database was set up with the right parameters.

Cluster and Version Information

  • pg_control version number: 1800
  • Catalog version number: 202506291
  • Database system identifier: 7658634883587915935
  • Database cluster state: in production

The pg_control version number tells us about the format of the pg_control file. Every time PostgreSQL has a release, the control file format changes. PostgreSQL uses this value to make sure that the data directory matches the server version.

The Catalog version number is about the internal system catalog format. If this value changes when we move to a PostgreSQL release, we cannot just use the same data directory with the new version. This is because the internal catalog structures have changed.

The Database system identifier is an identifier that we get when we create a cluster using initdb. It is unique to the cluster. It helps replication and backup tools work with the right database cluster.

The Database cluster state shows us what is happening with the cluster now. If it says in production, that means the server stopped properly, or it is working normally.

Control File Timestamp

  • pg_control last modified: Saturday 01 August 2026 07:48:57 PM

This indicates when PostgreSQL last updated the pg_control file. The file is modified whenever important cluster metadata changes, such as during checkpoints or clean shutdowns.

Checkpoint Information

  • Latest checkpoint location
  • Latest checkpoint's REDO location
  • Latest checkpoint's REDO WAL file
  • Latest checkpoint's TimeLineID
  • Latest checkpoint's PrevTimeLineID
  • Latest checkpoint's full_page_writes

Time of the latest checkpoint

A checkpoint is a point where PostgreSQL writes modified data pages from memory to disk and records a consistent recovery point.

These fields describe the most recent checkpoint.

The latest checkpoint location is the WAL position where the checkpoint record was written.

REDO location marks the point where crash recovery would begin if the server stopped unexpectedly.

REDO WAL file identifies the WAL segment containing that REDO position.

TimeLineID identifies the current WAL timeline. A new timeline is created after recovery or failover.

Previous TimeLineID stores the timeline from which the current one originated.

full_page_writes shows whether PostgreSQL records complete page images in WAL after checkpoints. Keeping this enabled helps prevent page corruption after crashes.

The time of the latest checkpoint records exactly when the last checkpoint was completed.

These values are especially useful when diagnosing crash recovery, replication, or WAL-related issues.

Transaction Information

The latest checkpoint has important values.

These are the NextXID, the NextOID, the NextMultiXactId, the NextMultiOffset, the oldestXID, the oldestActiveXID, and the oldestMultiXid of the checkpoint.

These values are used by PostgreSQL to keep track of its counters for objects and transactions.

PostgreSQLs NextXID is the next transaction ID that will be assigned to a transaction.

The NextOID is the object identifier that will be used for database objects that need OIDs.

The NextMultiXactId is used when many transactions try to lock the row at the same time.

It is the MultiXact identifier that will be used in this situation.

The NextMultiOffset points to the available space in the MultiXact storage area.

The oldestXID is the transaction that PostgreSQL still needs to keep.

The oldestActiveXID is the transaction that was still active when the last checkpoint happened.

The oldestMultiXid is the MultiXact that PostgreSQL still needs.

These counters are very important because they help PostgreSQL manage things

They help with transaction visibility and row locking.

They also help with vacuum operations.

This means that PostgreSQL can ensure that transactions are handled correctly and that the database is kept clean and up-to-date.

Recovery and Backup Information

  • Minimum recovery ending location
  • Backup start location
  • Backup end location
  • End-of-backup record required

These fields are mainly used during backup and recovery operations.

Minimum recovery ending location indicates the WAL position required before recovery can finish.

Backup start location and Backup end location record the WAL positions of a backup.

When both locations are 0/0, no online backup is currently active.

The end-of-backup record required shows whether PostgreSQL expects an end-of-backup record before recovery can complete.

For a running database, without an active backup, these fields typically remain at their default values.

Stored Server Configuration

  • wal_level setting
  • wal_log_hints setting
  • max_connections setting
  • max_worker_processes setting
  • max_wal_senders setting
  • max_prepared_xacts setting
  • max_locks_per_xact setting
  • track_commit_timestamp setting

The pg_control file stores important server settings because they directly affect the layout of the data directory and the WAL.

For this cluster:

wal_level is set to replica, allowing streaming replication and physical backups.

Wal_log_hints is disabled.

Max_connections allows up to 100 client connections.

Max_worker_processes is configured to 8 background worker processes.

Max_wal_senders allows up to 10 WAL sender processes for replication.

Max_prepared_xacts is 0, meaning two-phase commits are disabled.

Max_locks_per_xact defines the number of lock entries reserved for each transaction.

Track_commit_timestamp is disabled, so PostgreSQL does not store commit timestamps.

These values must remain compatible when starting the cluster. PostgreSQL validates them during startup to prevent configuration mismatches.

Storage Characteristics

These are the things that decide how PostgreSQL stores data internally.

The metadata includes maximum data alignment, database block size, and blocks per segment of relation. This also includes the WAL-related metadata like WAL block size, bytes per WAL segment, etc. Also includes the maximum length of identifiers, maximum columns in an index, maximum size of a toasted chunk, size of the large object chunk, date/time type storage, float8 argument passing, and the data page checksum version number. It also includes the default char data signedness, etc.

These values tell us how PostgreSQL stores data.

The Database block size is 8192 bytes. This means that each table and index page uses 8 KB.

The Blocks per segment of relation decides when PostgreSQL makes another segment file for very large tables.

The WAL block size is also 8 KB.

The Bytes per WAL segment shows that each WAL file is 16 MB.

The Maximum length of identifiers is 64 bytes. This includes PostgreSQL table names, PostgreSQL column names, and other PostgreSQL object names.

The maximum number of columns in an index shows that a single PostgreSQL index can have up to 32 columns.

The Maximum size of a TOAST chunk says how large each chunk of PostgreSQL values can be when PostgreSQL stores them outside the main PostgreSQL table.

The Size of a large-object chunk defines the size used for PostgreSQL objects.

The Date/time type storage indicates that PostgreSQL timestamps are stored as 64-bit integers.

The Float8 argument passing describes how PostgreSQL floating-point values are passed internally.

The Data page checksum version shows that page checksums are enabled. This helps PostgreSQL detect data corruption.

The Default character data signedness records whether the underlying platform treats the PostgreSQL char type as signed or unsigned.

These PostgreSQL values are fixed when the cluster is initialized. They cannot be changed without making a cluster.

Authentication Nonce

  • Mock authentication nonce

This is a value that PostgreSQL uses when it is testing how people log in and handling the rules for talking to the server. The server takes care of this value by itself, and the person in charge of the system does not need to do anything with the authentication nonce. The authentication nonce is something that the server uses to help with authentication nonce and it does what it needs to do without any help from the administrator.

The pg_controldata utility provides a snapshot of the PostgreSQL cluster by reading information directly from the pg_control file. It reports the cluster's state, checkpoint details, transaction counters, recovery metadata, important configuration settings, and storage characteristics without starting the database server. Because all of this information comes directly from the control file, pg_controldata is one of the most useful tools for inspecting a PostgreSQL cluster, verifying its configuration, and troubleshooting startup, recovery, backup, or replication issues.

WhatsApp