Physical backups and point-in-time recovery with pg_basebackup and WAL archiving
A base backup plus a continuous archive of WAL files lets you restore a PostgreSQL cluster to any moment after the backup, not just to the time of the last dump.
Not checked by a trusted editor yet Last edited Outdated?
PostgreSQL writes every change to the write-ahead log (WAL) before changing the data files. If you keep a copy of the data directory (a base backup) and every WAL file written since then, you can replay the WAL on top of the copy and stop at any point you like. This is point-in-time recovery (PITR), and it is how you undo “someone ran a DELETE without WHERE at 14:03”.
Physical backups copy the whole cluster: every database, plus roles. They only restore to the same major version and platform. Logical dumps from pg_dump cannot be combined with WAL replay.
Part 1: archive every WAL segment
WAL is written in segment files (16MB by default). When a segment is complete, the server runs archive_command (or an archive module set in archive_library) to copy it somewhere safe. %p is replaced by the file’s path and %f by its name:
wal_level = replica
archive_mode = on
archive_command = 'test ! -f /mnt/server/archivedir/%f && cp %p /mnt/server/archivedir/%f'
archive_timeout = 60
The command must exit with zero only when the file is safely archived; on a non-zero exit the server keeps the segment and retries. It should also refuse to overwrite an existing file, which is what the test ! -f part does. archive_mode needs a restart; archive_command only a reload. archive_timeout forces a segment switch on quiet systems so the archive does not fall far behind.
If archiving keeps failing, WAL piles up in pg_wal/ until the disk fills. Watch the pg_stat_archiver view (failed_count, last_failed_wal) and the free space on the WAL volume.
Part 2: take base backups
pg_basebackup copies a running cluster over the replication protocol. It needs a role with the REPLICATION attribute (or a superuser) and a replication line in pg_hba.conf:
pg_basebackup -h db1.example.com -U replicator -D /backup/base/2026-10-15 -Ft -z -X stream -P -c fast
-D: target directory; it must be empty or not exist.-Ftwrites tar files (-Fp, the default, mirrors the data directory layout);-zcompresses the tar output.-X stream(the default) streams the WAL needed to make the backup consistent on its own.-c fastrequests an immediate checkpoint instead of a spread one, so the backup starts sooner.-Pshows progress.
Recent versions also support incremental base backups (pg_basebackup --incremental, server version 17 and later), which need WAL summarization enabled and are combined with pg_combinebackup before use.
Part 3: recover to a point in time
Warning: recovery replaces the data directory. Practice on a separate machine first, and if you recover in place, keep the old data directory (or at least any unarchived files in pg_wal/) until you have verified the result.
- Stop the server.
- Move the current data directory aside, if space allows.
- Restore the base backup into an empty data directory with the right owner and permissions (
postgres, mode 0700). - Empty
pg_wal/of files from the backup and copy in any unarchived WAL you saved. - Set
restore_commandand a recovery target inpostgresql.conf. - Create an empty
recovery.signalfile in the data directory. - Optionally block normal users in
pg_hba.conf, then start the server and watch the log. - Check the data. When it is right, end recovery and re-open access.
restore_command = 'cp /mnt/server/archivedir/%f %p'
recovery_target_time = '2026-10-15 14:02:00+00'
recovery_target_action = 'pause'
restore_command must return non-zero when a file is not in the archive; that is normal at the end of recovery. With recovery_target_action = 'pause' the server stops replaying at the target and lets you look around read-only; SELECT pg_wal_replay_resume(); then ends recovery, while 'promote' ends it automatically. The target must be later than the end of the base backup.
Timelines
Each completed recovery starts a new timeline, visible as the first eight hex digits of WAL file names (for example 00000002...). A small .history file records where the branch happened. Timelines stop a recovered server from overwriting WAL that belongs to the original history, so you can try several recovery targets from the same archive.
In practice
Most teams use a dedicated tool such as pgBackRest or Barman that wraps these steps: parallel and incremental backups, retention, checksums, and archive management. The concepts stay the same, and knowing them makes those tools far easier to operate.
Official documentation
See also
- 0202 Back up and restore PostgreSQL with pg_dump, pg_restore and pg_dumpall Make logical backups of one database with pg_dump, of roles and the whole cluster with pg_dumpall, and restore them with pg_restore or… Beginner · How-to · Linux Article Backup & restore 15 Oct 2026
- 0205 Set up PostgreSQL streaming replication with a hot standby Step-by-step: prepare a primary, clone it with pg_basebackup, start a read-only standby that streams WAL, check it works, and understand promotion and… Advanced · How-to · Linux Article Replication & high availability 15 Oct 2026
- 0206 Nightly PostgreSQL backup script with pg_dump and rotation A bash script for cron that dumps cluster roles plus every database in custom format into a dated folder, checks each archive,… Intermediate · How-to · Linux Script Backup & restore 15 Oct 2026
- 0208 Check PostgreSQL replication lag with a monitoring script A bash check that detects whether it runs on a primary or a standby, measures replication lag in bytes and seconds, and… Advanced · How-to · Linux Script Replication & high availability 15 Oct 2026
- 0257 Run PostgreSQL properly on a Linux server: install, lock down, back up, monitor and patch Set up PostgreSQL 18 from the official repository for one application: a dedicated role and database, SCRAM logins from one app server… Intermediate · Tutorial · Linux Article Backup & restore · Install & connect · Roles & administration 15 Oct 2026
Repos in the wild
- pgBackRest: backup and restore for PostgreSQL pgbackrest/pgbackrest pgBackRest is a widely used PostgreSQL backup tool with parallel full, differential and incremental backups, WAL archiving, encryption and S3, Azure or GCS repositories. GitHub
History
Every saved edit is kept. The plot on the sleeve draws one line per edit. Open any edit to see exactly what changed.
- Commitpedia +4,547 chars