Verify a PostgreSQL Base Backup with pg_verifybackup
You will check a plain-format PostgreSQL base backup against the backup_manifest created with it, verify the data file checksums and check the WAL needed for recovery. A successful result is evidence that the backup copy is intact, not proof that a restored database will serve the right data.
The route
Jump straight to the step you need, or tick off Done means at the end.
Allow about ten minutes for a small backup, plus the time needed to read the whole data set when checksums are enabled. You need PostgreSQL 16's client utilities and a readable backup directory. The installed binary here is PostgreSQL 16.15, at /usr/lib/postgresql/16/bin/pg_verifybackup. It is not on this shell's PATH, so the examples use its full path. Use the matching PostgreSQL major version for the backup's WAL checks.
1. Confirm the verifier and backup format
Check the binary before pointing it at a real backup. This is an ordinary, read-only command and does not need elevated privileges:
$ /usr/lib/postgresql/16/bin/pg_verifybackup --version
pg_verifybackup (PostgreSQL) 16.15 (Ubuntu 16.15-0ubuntu0.24.04.1)
The backup must be in the plain directory format produced by pg_basebackup. A tar-format backup must be extracted before verification. Do not verify a directory while another process is still copying files into it: a changing tree can produce missing-file or checksum errors that do not describe a completed backup.
Checkpoint: identify the directory that contains the backup data and, normally, backup_manifest at its top level:
$ ls -l /srv/backups/postgresql/base-2026-09-26/backup_manifest
If this says the file does not exist, stop here and find the manifest or confirm that the backup was created with manifest generation enabled. The verifier cannot reconstruct a missing manifest.
2. Run the complete verification
Pass the backup directory as the final argument. The default run checks the manifest, compares the file list and sizes, reads files to compare their checksums, and parses the WAL records needed to recover the backup:
$ /usr/lib/postgresql/16/bin/pg_verifybackup \
/srv/backups/postgresql/base-2026-09-26
Success is represented by exit status 0. Capture it immediately if you need to record the result:
$ status=$?
$ printf 'pg_verifybackup exit status: %s\n' "$status"
pg_verifybackup exit status: 0
Do not rely on a clean-looking terminal alone in a script. A non-zero status means that the manifest could not be read or verified, files differ, checksums do not match, or the required WAL could not be read or parsed. Without --exit-on-error, the command continues and reports more than one problem when it can.
3. Read failures before changing anything
A checksum failure means the file no longer matches the content recorded in the manifest. An extra or missing file usually means the copy is incomplete or was changed after the backup. Preserve the original backup while investigating. Do not delete the reported file, copy a replacement over it, or add an ignore rule just to obtain a green result.
The verifier deliberately ignores postgresql.auto.conf, standby.signal, recovery.signal, anything under pg_wal, and the backup's own manifest when comparing the tree. These exceptions account for normal restore preparation; they do not make unrelated changes safe.
For a quicker first diagnosis, stop at the first reported problem:
$ /usr/lib/postgresql/16/bin/pg_verifybackup \
--exit-on-error /srv/backups/postgresql/base-2026-09-26
Use --ignore=RELATIVE_PATH only when a known, documented file or subtree is intentionally outside the manifest. The path is relative to the backup directory, and the option suppresses extra, missing, size and checksum complaints for that path. It does not repair the backup. Multiple --ignore options are allowed, so review every one before storing the command in a job.
4. Verify an external manifest or WAL archive
If the manifest was moved out of the backup directory for separate storage, name it explicitly. This command reads the manifest; it does not move, overwrite or remove either file:
$ /usr/lib/postgresql/16/bin/pg_verifybackup \
--manifest-path /srv/backup-manifests/base-2026-09-26.backup_manifest \
/srv/backups/postgresql/base-2026-09-26
If the needed WAL is stored outside the backup's pg_wal directory, point the verifier at that directory:
$ /usr/lib/postgresql/16/bin/pg_verifybackup \
--wal-directory /srv/wal-archive \
/srv/backups/postgresql/base-2026-09-26
WAL parsing is version-specific. Use the pg_verifybackup and pg_waldump from the PostgreSQL version relevant to the backup's WAL. The data-file checks can work across server versions that generate a manifest, but that does not make cross-version WAL verification interchangeable.
5. Choose speed or visibility deliberately
--skip-checksums avoids reading every data file. It still checks file presence and sizes, but it cannot detect content changes that leave a file at the same size. Use it for a quick inventory check, then run the default full verification before treating the backup as release-ready.
$ /usr/lib/postgresql/16/bin/pg_verifybackup \
--skip-checksums /srv/backups/postgresql/base-2026-09-26
--progress reports checksum progress for a large backup. It cannot be combined with --quiet. The quiet form is useful for a scheduled check where only errors should be printed:
$ /usr/lib/postgresql/16/bin/pg_verifybackup \
--quiet /srv/backups/postgresql/base-2026-09-26
$ printf 'status=%s\n' "$?"
status=0
Normally run as the account that owns the backup copy. Use sudo only when filesystem permissions genuinely require it, and avoid making backup directories broadly readable merely to remove that requirement.
Done means
- The backup is a complete, stable plain-format directory with a readable manifest.
- The matching PostgreSQL 16.15 verifier completed with exit status 0.
- The full run included checksums and required WAL parsing, unless the omission is recorded.
- Any ignored path, external manifest or external WAL directory is documented and reviewed.
- A separate test restore has confirmed that the recovered cluster starts and contains the expected data.