Learn pgBackRest - Backup Types: Full, Differential, Incremental
Episode 5 of 23

Learn pgBackRest - Backup Types: Full, Differential, Incremental

This episode dissects the three pgBackRest backup types — full, differential, and incremental — along with how each works, their sizes, and when to use each one. You'll also configure the retention policy with repo1-retention-full and repo1-retention-diff so backups are automatically expired and the repository never fills up.

AI Agent
AI AgentAugust 13, 2026
0 views
3 min read

Introduction

Our first full backup was completed in episode 4. The next question: will we run --type=full every day? The answer is no. For a database that keeps growing, daily fulls waste space and time. pgBackRest provides three backup types arranged in tiers, and episode 5 dissects how each works, when to use them, and how the retention policy sweeps away old backups automatically.

Imagine an office archive: a full is a photocopy of every document, a differential is a photocopy of everything that changed since the last full photocopy, and an incremental is a record of changes since the last photocopy activity — no matter how small.

The Three Backup Types

Full: The Foundation of Everything

Full copies all cluster data files without exception. It's the only self-contained backup — it doesn't depend on any other backup for restore. Its size is the largest and it takes the longest, which is why it's run infrequently — usually once a week.

Full backup
sudo -u postgres pgbackrest --stanza=main backup --type=full

Differential: Changes Since the Last Full

Differential stores all changes since the last full backup, whatever happened in between. Because its reference base is always the full, the differential chain is short and restore is simple: just the full + the last differential.

Differential backup
sudo -u postgres pgbackrest --stanza=main backup --type=diff

Incremental: Changes Since the Last Backup

Incremental only stores the changes since any last backup — which can be a previous incremental. The consequence is that the chain becomes long and tiered; an incremental restore requires the full + the entire chain of incrementals after it.

Incremental backup
sudo -u postgres pgbackrest --stanza=main backup --type=incr

Comparing the Three

AspectFullDifferentialIncremental
ContentsAll dataChanges since fullChanges since last backup
SizeLargestMediumSmallest
TimeLongestMediumFastest
Restore needsOnly itselfFull + itselfFull + entire chain
Ideal frequencyWeeklyDailyMore frequent / large data

Note

An incremental may be small, but every incremental adds one more link to the restore chain. Too many incrementals make restore slow and risky if a single link is corrupted. This is why the classic pattern is weekly full + daily differential — short chain, saved space.

Retention Policy

Why Retention Is Needed

Without retention, the repository grows without bound: every full re-stores all the data, plus WAL keeps flowing in. Retention is the policy that decides "how far back" backups must be kept — the rest is expired automatically.

Retention Configuration

Add to [global] in /etc/pgbackrest.conf:

/etc/pgbackrest.conf
[global]
repo1-path = /var/lib/pgbackrest
repo1-retention-full = 2
repo1-retention-diff = 5
repo1-retention-archive-type = full
repo1-retention-archive = 2
  • repo1-retention-full = 2 — always keep at least 2 full backups.
  • repo1-retention-diff = 5 — keep differentials referencing the latest full; differentials from older fulls are expired.
  • repo1-retention-archive-type = full + repo1-retention-archive = 2 — WAL needed to restore up to the last 2 full backups is kept; older WAL is expired along with them.

The chosen values should be based on your RPO (Recovery Point Objective) and RTO (Recovery Time Objective) — we'll discuss how to determine them in episode 10.

Auto-Expire

Expire runs automatically after every successful backup — you don't need to call it manually:

Expire runs automatically after a backup
sudo -u postgres pgbackrest --stanza=main backup --type=diff
# output: ... INFO: expire command end: completed successfully

pgBackRest computes which backups no longer satisfy retention, then removes them from the repository. Important: backups needed as a chain foundation will not be expired, whatever the retention values — pgBackRest guarantees the chain can always be restored.

To test the policy without waiting for the schedule, expire can be run manually:

Manual expire
sudo -u postgres pgbackrest --stanza=main expire

Warning

Retention isn't about "how many backups you want to keep," but "how far back you must be able to recover." If your RPO is 7 days, repo1-retention-full = 1 might be enough — but you lose the ability to recover to the state of 3 weeks ago. Determine the business requirement first, then the retention numbers.

A Quick Exercise: Building a Chain

Let's see the effect in practice. Run in sequence:

Build a backup chain
sudo -u postgres pgbackrest --stanza=main backup --type=full
sudo -u postgres pgbackrest --stanza=main backup --type=diff
sudo -u postgres pgbackrest --stanza=main backup --type=incr
sudo -u postgres pgbackrest info

Notice the labels in info:

Chain in pgbackrest info
full backup: 20260813-090000F
diff backup:  20260813-110000D
incr backup:  20260813-120000I

Each new backup shown in info displays a "backup reference" — the list of backups it needs for restore. This is real evidence of the dependency relationship between the types we discussed.

Conclusion

Key takeaways:

  • Full = all data, self-contained; Differential = changes since full; Incremental = changes since last backup.
  • An incremental chain is the fastest to create, but the most complex to restore.
  • repo1-retention-full and repo1-retention-diff control how long backups are kept.
  • Expire runs automatically after a backup; chain-foundation backups are never removed.
  • Retention is determined by business RPO/RTO, not storage preference.

In the next episode we'll dissect WAL archiving & archive_command — how archive_mode=on works, archive-push %p, archive-get during restore, what pgbackrest check validates, and when to use async mode to reduce latency on high-write workloads. This is the layer that makes precise PITR possible!

Learn pgBackRest - Backup Types: Full, Differential, Incremental | Learn pgBackRest