This replication error occurs when a standby PostgreSQL server's database system identifier doesn't match the primary server's identifier, indicating they are not properly related. This happens when the standby wasn't created from a backup of the primary.
PostgreSQL's database system identifier is a unique identifier assigned to each database cluster at initialization time. During physical replication setup, the standby server must be an exact binary copy of the primary to maintain data consistency. When this error occurs, it means you're trying to set up replication between two unrelated database clusters—the standby is either from a different PostgreSQL instance entirely or was not properly cloned from the primary. The error typically includes a DETAIL line showing both identifiers: "The primary's identifier is XXXXXXX, the standby's identifier is YYYYYYY." These numbers will be different if the standby wasn't created from the primary's backup.
First, ensure the standby server is completely stopped to prevent data corruption:
sudo systemctl stop postgresql
# or for a specific version
sudo systemctl stop postgresql@15-mainVerify it's stopped:
sudo systemctl status postgresqlBefore removing, back up the current data directory in case you need to investigate:
# Backup the existing standby data
sudo mv /var/lib/postgresql/15/main /var/lib/postgresql/15/main.bak
# Or if using a different version/path:
sudo mv /path/to/postgres/data /path/to/postgres/data.bakThen create a fresh, empty directory with correct permissions:
sudo mkdir -p /var/lib/postgresql/15/main
sudo chown postgres:postgres /var/lib/postgresql/15/main
sudo chmod 700 /var/lib/postgresql/15/mainThis is the critical step. Run pg_basebackup on the standby to copy the entire database cluster from the primary:
sudo -u postgres pg_basebackup \
-h <primary_ip_or_hostname> \
-p 5432 \
-U replication \
-D /var/lib/postgresql/15/main \
-Fp \
-Xs \
-RFlag explanations:
- -h: IP or hostname of the primary server
- -p: PostgreSQL port on the primary (default 5432)
- -U replication: User with replication privileges (must exist on primary)
- -D: Destination data directory on standby
- -Fp: Plain format (not tar)
- -Xs: Stream WAL (Write-Ahead Logs) while backup runs
- -R: Automatically create standby.signal and postgresql.auto.conf
Example:
sudo -u postgres pg_basebackup \
-h 192.168.1.10 \
-p 5432 \
-U replication \
-D /var/lib/postgresql/15/main \
-Fp \
-Xs \
-RThis process may take several minutes depending on database size. Wait for it to complete.
After pg_basebackup completes, verify the standby configuration files were created correctly:
# Check standby.signal exists (indicates standby mode)
sudo ls -la /var/lib/postgresql/15/main/standby.signal
# Check postgresql.auto.conf was created
sudo cat /var/lib/postgresql/15/main/postgresql.auto.confThe postgresql.auto.conf should contain lines like:
primary_conninfo = 'host=192.168.1.10 port=5432 user=replication password=...'If these files don't exist, the pg_basebackup likely failed. Check the output above for error messages.
Now start PostgreSQL with the correct data:
sudo systemctl start postgresql
# or for specific version
sudo systemctl start postgresql@15-mainCheck the status:
sudo systemctl status postgresqlCheck the logs for any errors:
sudo tail -f /var/log/postgresql/postgresql-15-main.logYou should see messages like:
LOG: database system was interrupted while in recovery at log time 2024-01-15 10:30:45 UTC
LOG: entering standby mode
LOG: started streaming WAL from primary at 0/3000000 on timeline 1Connect to the primary server and check replication status:
# On primary
psql -U postgresThen run:
SELECT slot_name, slot_type, active FROM pg_replication_slots;
SELECT pid, usename, application_name, client_addr, state FROM pg_stat_replication;You should see the standby listed as an active replication connection. Example output:
pid | usename | application_name | client_addr | state
---------+---------+--------------------+--------------+----------
12345 | replication | walreceiver | 192.168.1.20 | streamingIf the standby is not listed, check the primary logs and standby logs for connection errors.
Replication User Setup: The user specified with -U must have REPLICATION privilege on the primary. Create it with:
CREATE ROLE replication WITH LOGIN REPLICATION;
ALTER ROLE replication WITH PASSWORD 'secure_password';Then add to primary's pg_hba.conf:
host replication replication 192.168.1.20/32 md5Synchronous Replication: For high-availability setups, configure synchronous_commit on the primary to wait for standby acknowledgment before committing transactions. This adds latency but ensures zero data loss.
WAL Archive Strategy: For production replication, configure WAL archiving on the primary to handle WAL files that arrive after the backup completes. Without this, the standby might fall behind if the primary has high write volume.
Network Issues: If pg_basebackup fails with connection refused, verify the primary's listen_addresses includes the standby IP and pg_hba.conf allows replication connections from the standby.
Large Databases: For databases over 100GB, pg_basebackup may take a long time. Monitor the primary's CPU and disk I/O during backup. Use -j flag for parallel backup on PostgreSQL 10+:
pg_basebackup -h primary -U replication -D /var/lib/postgresql/15/main -j 4Failover Considerations: Once replication is confirmed working, plan your failover procedure using tools like pg_ctl promote (manual) or replication manager extensions like repmgr for automated failover.
insufficient columns in unique constraint for partition key
How to fix "insufficient columns in unique constraint for partition key" in PostgreSQL
ERROR 42501: must be owner of table
How to fix "must be owner of table" in PostgreSQL
trigger cannot change partition destination
How to fix "Trigger cannot change partition destination" in PostgreSQL
SSL error: certificate does not match host name
SSL error: certificate does not match host name in PostgreSQL
No SSL connection
No SSL connection to PostgreSQL