Back Up WAL Archives for PITR
Back up WAL archives for PITR in this hands-on PostgreSQL Tutorial lesson. Learn the core concept, step-by-step process, troubleshooting, and what to study next.
Focus: back up wal archives for pitr
You've configured PostgreSQL archiving, your base backups are scheduled, and everyone high-fives after a successful restore drill. But then the disk holding your WAL archive fills up, or a fire in the colo takes down the archive server, and you realize your PITR strategy has a single point of failure. Backing up WAL archives for PITR is the unsung hero of disaster recovery: without a redundant copy of your WAL, you can't replay transactions past your last base backup. This lesson gives you a clear, practical approach to protect those archives so your point-in-time recovery actually works when you need it.
The problem this lesson solves
Your PostgreSQL base backup gives you a consistent snapshot at a specific time, but the WAL archives store every change since then. If you lose those archives, you can only recover up to the base backup — effectively losing all subsequent transactions. In production, that can mean hours or days of lost work, which is often worse than a complete crash.
Common failure scenarios include:
- Disk failure: The storage holding your
archive_commandoutput dies. - Human error: Someone accidentally deletes the archive directory while cleaning up.
- Ransomware or corruption: An attacker (or a bug) encrypts or corrupts your archive files.
- Site-wide outage: The machine hosting the archive goes down permanently.
Pro tip: Your base backups are only as good as your WAL archives. If you can't restore the WAL, you can't replay to the point you need. Always treat WAL archives as critical production data.
Core concept / mental model
Think of PITR as a time machine: the base backup is a photo of your database at a moment in time, and WAL archives are the frames between that photo and now. Without frames, you can't build a continuous movie — you just have a static picture.
Definitions:
- WAL archives: Copy of WAL segments shipped to a separate location by
archive_command. - PITR: Point-in-time recovery — replaying WAL from a base backup up to a target time or transaction ID.
- Archive redundancy: Keeping a second, independent copy of WAL archives to guard against loss.
Why a separate backup matters: The WAL archive is not a backup of itself. If you use the same storage device as your database, a single disk failure kills both. Your archive backup should be isolated: different disk, different server, different physical site.
How it works step by step
Backing up WAL archives is conceptually like backing up any critical file set, but with special considerations for consistency and continuity.
- Ensure archive_mode is on and
archive_commandis reliably shipping WAL to your primary archive location. - Choose a secondary archive location — this is what you'll back up to.
- Copy WAL archives to the secondary location using tools like
rsync,scp, orpg_basebackup(for full backups). - Automate the copy with a cron job or a continuous sync tool so the backup stays current.
- Test restoration from the secondary archive to confirm it's usable.
Cause → effect: If you back up WAL archives regularly, you can recover to any point in time after your last base backup. If you don't, your base backup alone is insufficient.
Hands-on walkthrough
Let's get your WAL archives backed up. We'll assume a primary archive at /var/lib/postgresql/wal_archive and set up a secondary location at /backup/wal_archive.
1. Verify your current archive setup
First, check that archiving is actually working:
SHOW archive_mode;
SHOW archive_command;
SELECT * FROM pg_stat_archiver;
Expected output (example):
archive_mode | on
archive_command | 'test ! -f /var/lib/postgresql/wal_archive/%f && cp %p /var/lib/postgresql/wal_archive/%f'
last_archived_wal | 000000010000000000000001
If last_archived_wal is NULL, archiving isn't running — fix that first.
2. Create a secondary archive directory
mkdir -p /backup/wal_archive
chown postgres:postgres /backup/wal_archive
3. Copy WAL archives with rsync
Rsync is efficient — it only transfers new files:
rsync -av --ignore-existing /var/lib/postgresql/wal_archive/ /backup/wal_archive/
The --ignore-existing flag keeps your secondary archive append-only. Expected output shows which files were copied:
sent 1,234 bytes received 2,345 bytes total size 1,789,456
4. Automate with cron
Add a cron job (as the postgres user) to sync every minute:
crontab -e -u postgres
* * * * * rsync -av --ignore-existing /var/lib/postgresql/wal_archive/ /backup/wal_archive/ >/dev/null 2>&1
5. Test recovery from the secondary archive
This is non-negotiable. You must verify the backup works:
pg_basebackup -D /tmp/restore_test -U postgres -R
cp /backup/wal_archive/* /tmp/restore_test/pg_wal/
# create a recovery.signal file and configure recovery_target_time if desired
pg_ctl -D /tmp/restore_test start
If PostgreSQL starts and you see expected data, your backup is solid.
Pro tip: Always test restoration from the backup itself, not just the primary archive. If you only test the primary, you'll be surprised during a real disaster.
Compare options / when to choose what
There are several ways to back up WAL archives. Your choice depends on your environment and recovery objectives.
| Method | Pros | Cons | Best for |
|---|---|---|---|
| rsync cron job | Simple, low overhead, incremental | Might miss changes between runs (seconds of risk) | Small to medium environments, on-premise |
| Continuous sync (e.g. pgBackRest, barman) | Keeps archives near real-time, integrated with PostgreSQL | More setup complexity | Production systems requiring minimal data loss |
| Cloud object store (S3, GCS) | Off-site, durable, scalable | Network latency, egress costs | Geo-redundancy, compliance requirements |
Decision framework:
- If you need simple and cheap, use rsync + cron.
- If you need minimal data loss window, use barman or pgBackRest with
receive-walorarchive-push. - If you need off-site protection, replicate to cloud storage.
Troubleshooting & edge cases
WAL archive backup is behind
Check the timestamp of the newest file in your secondary archive:
ls -lt /backup/wal_archive | head
If it's stale, check the cron job's logs and that rsync permissions are correct.
Rsync permission denied
This is a common one. Make sure the postgres user can write to /backup:
chown -R postgres:postgres /backup
Archive files are corrupt on the secondary
If pg_verify_checksums fails or pg_waldump can't read a file, your backup is corrupt. This can happen if you copy a file while it's still being written to. Ensure your archive command uses %p and %f correctly, and that you use --ignore-existing — never copy over an existing file.
Backup is empty after a crash
If you only run cron every minute, a crash could lose the last 59 seconds of WAL. Consider using archive_command to ship to both locations simultaneously, or use a tool with WAL streaming.
Disk full on secondary
Monitor disk usage. A full secondary can silently fail your backup. Include a simple check in your cron script:
if [ $(df --output=pcent /backup | tail -1 | tr -d '%') -gt 90 ]; then
echo 'WAL backup disk nearly full' | mail -s 'alert' admin@example.com
fi
What you learned & what's next
You now understand why backing up WAL archives is critical for PITR. You've built a simple, reliable backup process with rsync and cron, and you know how to test it. You also know alternative tools like barman and pgBackRest for more demanding requirements.
Key concepts solid now:
- Identify a secondary archive location distinct from your primary.
- Automate the copy to keep it current.
- Test restoration from the backup regularly — not just once.
- Monitor for failures.
Next step in this track: The next lesson moves from archival to restoration — you'll practice recovering to a specific point in time using a base backup and your backup WAL archives. This is where you'll see the payoff of all your careful backup work.
Practice recap
Set up a secondary archive for an existing PostgreSQL instance using rsync and a cron job. Then simulate a restoration from that backup — stop the server, use pg_basebackup to create a restore, apply your backup WAL, and verify the data. This hands-on drill ensures your PITR actually works under pressure.
Common mistakes
- Storing WAL archive backups on the same disk as the primary archive — defeats the purpose entirely.
- Using
rsyncwithout--ignore-existing, which can overwrite a corrupted primary archive onto your backup. - Never testing restoration from the backup itself, leading to surprises during a real disaster.
- Forgetting to monitor disk space or cron logs, so the backup silently fails for weeks.
- Assuming archive_mode is on but never checking
pg_stat_archiverfor failures.
Variations
- Use
barmanto manage WAL archive backups with built-in retention and recovery testing. - Stream WAL to a remote server with
pg_receivewalfor a near real-time backup. - Ship WAL to cloud storage (e.g., S3) using
archive_commandfor geo-redundancy.
Real-world use cases
- An e-commerce platform uses a cron-based rsync to keep hourly archives on a separate server for quick recovery without cloud costs.
- A SaaS provider uses barman to continuously back up WAL archives across availability zones, ensuring zero data loss within minutes.
- A financial institution replicates WAL archives to an S3 bucket in a different region to meet regulatory disaster recovery requirements.
Key takeaways
- WAL archives are as critical as base backups — losing them invalidates PITR.
- Always keep a separate, independent copy of WAL archives on a different device or site.
- Automate the backup with tools like rsync or barman to keep it current and reduce human error.
- Test restoration from the backup regularly to guarantee your recovery procedure works.
- Monitor the backup process and disk space to catch failures early.
- Choose the right tool based on your recovery time and data loss tolerance.
Keep learning
Related tutorials, quizzes, and articles for this topic.
Discussion
Questions, corrections, and tips help everyone reading this page.
0 comments
Add a comment
No comments yet — start the thread.