PostgreSQLXIII · Backup, Archiving and Point-in-Time RecoveryBackup
pg_basebackup: its role and its limits
What you'll learn
- Take a base backup with the flags that matter and know why each is there
- Verify a backup with pg_verifybackup and its manifest
- Take and reconstruct an incremental backup
- State what pg_basebackup cannot do
Prerequisites
Practice
Verified against PostgreSQL 18.x · PostgreSQL (comparison targets) 17.11, 16.15 · PostgreSQL (support calendar) 18, 17, 16, 15, 14 supported · pgBackRest 2.59.1 · PgBouncer 1.25.2 · Patroni 4.1.5 · Ubuntu (host baseline) 26.04 LTS · 2026-08-27
pg_basebackup is the low-level API from the previous lesson, driven
correctly by a program that holds one connection open, copies the right
files, excludes the right files, and writes backup_label. It ships
with PostgreSQL and it is the right starting point for physical backups.
Taking one
$ pg_basebackup -D /backup/base -Ft -z -Xstream -P -c fastwaiting for checkpoint
23854/23854 kB (100%), 0/1 tablespace
23854/23854 kB (100%), 1/1 tablespace$ ls -la /backup/base/-rw------- 1 postgres postgres 138651 backup_manifest
-rw------- 1 postgres postgres 3162227 base.tar.gz
-rw------- 1 postgres postgres 17091 pg_wal.tar.gzThree artefacts, and all three matter.
| File | What it is | If you lose it |
|---|---|---|
base.tar.gz | The data directory | No backup |
pg_wal.tar.gz | WAL generated during the backup | Backup cannot reach consistency |
backup_manifest | Checksums of every file | Nothing to verify against |
The flags that matter
-X stream (the default) opens a second connection and streams WAL
alongside the copy, so the backup contains everything it needs to reach
a consistent state on its own. The alternative, -X none, produces a
backup that is unusable without the WAL archive. That is a
legitimate choice when you have a reliable archive, and a common way to
end up with an unrestorable backup when you do not.
-c fast requests an immediate checkpoint. Without it the backup
waits for a spread checkpoint, which on a busy cluster with a large
checkpoint_timeout can be several minutes of doing nothing. fast
costs a burst of I/O, exactly as lesson XII-04 described.
-P shows progress. On a multi-hour backup this is the difference
between knowing it is working and hoping.
-Ft -z produces compressed tar files. -Fp produces a plain
directory — larger, and the format pg_combinebackup needs.
--checkpoint=spread is the polite option for a cluster where a
burst of checkpoint I/O would be noticed. It trades backup start latency
for a gentler write pattern.
-R writes standby.signal and the connection settings, turning
the backup into a standby. Part XIV uses this.
Verifying
$ pg_verifybackup -n /tmp/vbbackup successfully verifiedThe manifest lists every file with its size and checksum. Verification detects truncation, corruption in transit, and files that went missing between backup and storage. It does not prove the backup restores — only that the bytes are the bytes that were written. Proving a restore is lesson XIII-08.
Incremental backup
PostgreSQL 17 added incremental base backups, and they are the largest change to native backup capability in years. The prerequisite is WAL summarization.
$ ALTER SYSTEM SET summarize_wal = on; SELECT pg_reload_conf(); name | setting | source
---------------+---------+--------------------
summarize_wal | on | configuration fileWith summarization on, an incremental backup takes the previous backup’s manifest as its baseline:
$ pg_basebackup -D /backup/full -Fp -Xstream -c fast -P
# ... 2,000 rows updated, CHECKPOINT ...
pg_basebackup -D /backup/incr -Fp -Xstream -c fast -i /backup/full/backup_manifest -P130846/130846 kB (100%), 1/1 tablespace <- full
5189/131307 kB (3%), 1/1 tablespace <- incremental
$ du -sh /backup/full /backup/incr
144M /backup/full
24M /backup/incrThree per cent of the cluster sent. Unchanged blocks are replaced by stub files:
$ find /backup/incr -name 'INCREMENTAL.*' | wc -l671$ pg_combinebackup /backup/full /backup/incr -o /backup/merged
pg_ctl -D /backup/merged start
psql -p 5434 -c "SELECT count(*), count(*) FILTER (WHERE pad LIKE 'z%') FROM bulk"$ du -sh /backup/merged
145M /backup/merged
server started
rows | updated_rows
--------+--------------
400000 | 2000All 400,000 rows, and the 2,000 updated after the full backup carry their new values. The chain reconstructed correctly.
What pg_basebackup cannot do
- Back up a single database or table. It copies the whole cluster.
- Deduplicate across backups. Each full backup is a full copy.
- Manage retention. No expiry, no rotation, no catalogue.
- Parallelise the copy. One connection, one stream. On a very large cluster this is the practical ceiling.
- Encrypt. Compression, yes. Encryption is your problem.
- Resume. An interrupted backup starts over.
- Restore. There is no
pg_baserestore. Restoring is extracting the archive and configuring recovery yourself.
That list is the argument for the tools in lesson XIII-08. It is not an
argument against pg_basebackup, which is correct, always present, and
the right answer for a great many clusters.
What to take from this
pg_basebackupdrives the low-level API correctly. Prefer it to hand-rolled scripts.-X streammakes the backup self-sufficient;-X nonemakes it depend on your archive.- Keep
backup_manifestwith the backup, and runpg_verifybackup. - Incremental backups need
summarize_wal, and sent 3% — 24 MB against 144 MB — in a measured case. - An incremental is not a data directory.
pg_combinebackupreconstructs it, and every member of the chain must survive. - No deduplication, no retention, no parallelism, no encryption, no resume, and no restore command.
Cross-course references
- Linux for Production Sysadmins — Part XLVII (Backup strategy) covers retention arithmetic, which changes shape once a backup chain has dependent members rather than independent fulls.
- Observability for Production Sysadmins — Part XCI (Backup strategy) covers alerting on the age of the oldest usable full, which is the number an incremental chain makes non-obvious.
Quiz
Knowledge check · 6 questions
Q1. A nightly pg_basebackup uses -X none. The WAL archive has been silently failing for a week. What is the state of those seven backups?
Q2. A backup chain is one weekly full plus six nightly incrementals. Tuesday's incremental is lost to a storage fault. What can still be restored?
Q3. Incremental backups were enabled six months ago with wal_summary_keep_time left at its default. A monthly full plus daily incrementals is proposed. What breaks?
Q4. Which of these does pg_basebackup NOT do? Select all that apply.
Q5. Attempting to start an incremental backup directory as a cluster fails with a clear error rather than producing a partially populated database.
Q6. How does WAL summarization enable incremental backups, and what does it cost?
Passing score: 75%. Answers are checked in this browser.