Database Backup Strategies: Full, Incremental, and PITR

Learn database backup strategies: full, incremental, and differential backups. Point-in-time recovery, WAL archiving, and RTO/RPO planning.

published: reading time: 29 min read author: GeekWorkBench updated: June 17, 2026
Quick Summary

Database recovery depends on matching backup methods to tested recovery point and recovery time targets. This guide compares physical base backups, logical dumps, incremental and differential approaches, and PostgreSQL point-in-time recovery with archived WAL. It explains how to measure backup storage and restore time, validate backup chains, and test recovery in an isolated environment. Use the checklists and failure scenarios to turn provider features into a recovery plan your team has actually rehearsed.

Backup and Recovery: Full, Incremental, Differential, and Point-in-Time

Introduction

If production data is corrupted, deleted, or inaccessible, your backup and recovery strategy determines how much data you lose and how long service stays unavailable. Having backup files is not enough; teams need to know that restores work and meet their recovery targets.

This guide compares full, incremental, and differential backups, explains point-in-time recovery with WAL archiving, and covers recovery point and recovery time objectives. It also looks at restore testing and the limits of relying on cloud-managed backups alone.

For example, if an operator drops a table at 15:00, a base backup from 02:00 alone only restores the database to 02:00. Archived WAL lets you replay changes and recover to a point just before the mistake.

Backup Types Explained

Full Backups

A full physical base backup captures the database cluster’s files. A logical backup such as pg_dump captures selected database objects in a portable format. The right baseline depends on the restore method and tooling you choose.

# PostgreSQL full backup example
pg_basebackup -h localhost -U postgres -D /backups/full -Ft -z -P

Advantages:

  • Complete restoration in a single operation
  • Simple to understand and verify
  • No dependency on other backups for restore
  • Self-contained disaster recovery

Disadvantages:

  • Largest storage footprint
  • Longest backup duration
  • Maximum impact on production system I/O
  • Cannot be applied incrementally

Full backups are the foundation of any backup strategy. You should always have at least one full backup as your recovery base.

Incremental Backups

An incremental backup captures changes relative to an earlier backup. PostgreSQL 17 and later support incremental physical backups with pg_basebackup --incremental, using an earlier backup’s manifest; -X stream only streams WAL while the base backup runs.

# PostgreSQL 17+: incremental physical backup based on a prior backup manifest
pg_basebackup -h localhost -U postgres -D /backups/incr_$(date +%Y%m%d_%H%M%S) \
  --incremental=/backups/full/backup_manifest -Ft -z -P

Incremental backups depend on their reference backups and must be combined with pg_combinebackup before recovery. Older PostgreSQL releases need a backup tool that explicitly supports incremental backups.

Advantages:

  • Minimal storage consumption
  • Fast backup operations
  • Low production system impact
  • Frequent backups possible

Disadvantages:

  • Restore requires chain of all backups from last full
  • Complex restore procedures
  • Backup chain corruption means data loss
  • Longer recovery time

The key insight: incremental backups are delta changes only. To restore, you need the last full backup plus every incremental backup in sequence.

Differential Backups

A differential backup captures changes since the last full backup. PostgreSQL’s pg_basebackup does not provide a differential-backup mode; use a backup tool that documents this strategy if you need it.

Differential backup: changed data since the latest full backup
Restore set: latest full backup + latest differential backup

Advantages:

  • Smaller than full backups
  • Simpler restore than incremental (only need full + one differential)
  • Moderate backup duration
  • Good balance of storage and complexity

Disadvantages:

  • Larger than incremental backups (grows over time)
  • Backup duration increases as differential grows
  • Still requires full backup + one differential to restore

Differential backups offer a middle ground: you trade some storage for restore simplicity.

Understanding Point-in-Time Recovery

Point-in-time recovery (PITR) allows you to restore a database to any specific moment—not just the moment when a backup completed. This is essential for recovering from user errors, partial data corruption, or transactions that shouldn’t have happened.

How PITR Works

PITR relies on Write-Ahead Logging (WAL). Every database modification is written to a sequential log file before being applied to data files. This log captures:

  • Transaction begin and commit records
  • Every row-level change (insert, update, delete)
  • Page-level changes for efficiency
-- PostgreSQL: Configure WAL archiving
wal_level = replica
max_wal_senders = 3
archive_mode = on
archive_command = 'cp %p /archive/wal/%f'

To perform PITR:

  1. Restore the latest full backup to a recovery location
  2. Configure recovery settings in postgresql.conf and create a recovery.signal file in the restored cluster
  3. Replay archived WAL segments sequentially
  4. Database reaches target state and becomes available
# postgresql.conf in the restored cluster
restore_command = 'cp /archive/wal/%f %p'
recovery_target_time = '2026-03-26 14:30:00 UTC'

Create an empty recovery.signal file in the restored data directory before starting PostgreSQL. Recovery settings are no longer stored in recovery.conf.

WAL Archiving Considerations

WAL archiving is the backbone of robust backup strategies. Key considerations:

Archive Storage: WAL volume depends on the workload and can differ substantially from database write volume. Measure generated WAL over representative peak and quiet periods, then size the archive for that measured rate and your retention window.

Archive Verification: Untested WAL archives are worthless. Regularly verify that archived WAL can actually restore.

# Remove archived WAL older than a known restart point; this is cleanup, not verification
pg_archivecleanup /archive/wal 00000001000000000000001C

Archiving and replication serve different recovery needs: PITR replays archived WAL from a base backup. Streaming replication can keep a standby current for failover; its retention and recovery behavior depend on configuration.

Method Typical use Key consideration
WAL archiving Point-in-time recovery Archive frequency and gaps determine the recoverable window.
Physical streaming replication Standby and failover Replication lag and failover behavior must be monitored and tested.
Logical replication Selective data replication It is not a substitute for physical backups and WAL-based PITR.

RTO and RPO Planning

Recovery Time Objective (RTO) and Recovery Point Objective (RPO) are your contractual commitments to stakeholders about recovery capabilities.

Defining Your Objectives

RTO (Recovery Time Objective): Target time to restore service after an outage. This is a duration—typically hours or minutes.

RPO (Recovery Point Objective): Maximum acceptable data loss measured in time. If your RPO is 1 hour, you accept losing up to 1 hour of transactions.

These aren’t technical decisions—they’re business decisions. Work with stakeholders to define realistic objectives based on:

  • Cost of downtime per hour
  • Cost of data loss per transaction
  • Regulatory requirements
  • Customer expectations

Translating to Technical Requirements

Once you have RTO and RPO targets, translate them to technical specifications:

RPO Technical Requirement
0 (no data loss) Synchronous replication or synchronous commit
15 minutes Frequent WAL archiving + tested recovery
1 hour Hourly differential backups + WAL
24 hours Daily full backups
RTO Technical Requirement
Minutes HA architecture, automatic failover
Hours Tested restore procedures, on-call staff
Days Documented manual recovery procedures

The Math of Recovery

Calculate realistic recovery times:

def estimate_recovery_time(
    full_backup_size_gb: float,
    differential_size_gb: float,
    network_mbps: float,
    restore_speed_mbps: float,
    wal_replay_seconds: int
) -> dict:
    transfer_time = (full_backup_size_gb * 1024 * 8) / network_mbps  # seconds; decimal network Mbps
    restore_time = (full_backup_size_gb * 1024) / restore_speed_mbps  # seconds; MB/s
    wal_time = wal_replay_seconds

    total_restore_minutes = (transfer_time + restore_time) / 60
    total_rto_minutes = total_restore_minutes + (wal_time / 60)

    return {
        "transfer_minutes": round(transfer_time / 60, 1),
        "restore_minutes": round(restore_time / 60, 1),
        "wal_replay_minutes": round(wal_time / 60, 1),
        "total_rto_minutes": round(total_rto_minutes, 1)
    }

Cloud Backup Solutions

AWS RDS

Amazon RDS provides automated backups with configurable retention:

# RDS backup configuration (AWS Console or CLI)
aws rds modify-db-instance \
    --db-instance-identifier my-db-instance \
    --backup-retention-period 30 \
    --preferred-backup-window "03:00-04:00" \
    --preferred-maintenance-window "sun:04:00-sun:05:00"

Key features:

  • Automated daily backups with configurable retention (1-35 days)
  • Point-in-time recovery to any second within retention period
  • Manual snapshots for long-term retention
  • Cross-region snapshot copying for disaster recovery
  • Automated backup to S3 with encryption

Limitations:

  • Restore time depends on snapshot size and network transfer
  • PITR availability and retention depend on engine and configuration
  • Cross-region copy latency for disaster recovery

Azure SQL

Azure SQL provides automated backups with geo-redundancy options:

# Azure SQL backup configuration
Set-AzSqlDatabaseBackupShortTermRetentionPolicy \
    -ResourceGroupName "my-resource-group" \
    -ServerName "my-server" \
    -DatabaseName "my-database" \
    -RetentionDays 30

Key features:

  • Full backup every week, differential every 12 hours, log backup every 5-10 minutes
  • Point-in-time restore within retention period (7-35 days)
  • Long-term retention (LTR) for years
  • Geo-restore with RA-GRS redundancy
  • Active geo-replication for read scale and failover

Comparing Cloud Providers

Managed backup features vary by provider, database engine, service tier, region, and configuration. Verify the current retention window, PITR coverage, cross-region copy behavior, and long-term retention options for the specific service you plan to use. Treat provider documentation as a capability description, then test a restore in your own environment to measure its RTO and confirm application behavior.

Evaluation question Why it matters
What are the configured backup and PITR retention windows for this engine and service tier? Defaults and maximums vary by provider, engine, and configuration.
Can recovery use a separate region or account? Regional recovery needs a copy or replica outside the failure boundary.
How long does an actual restore take, including application cutover? The provider’s feature list does not establish your RTO.
Can required backups be retained for the applicable compliance period? Long-term retention may need a separate archive and restore procedure.

When to Use / When Not to Use Each Backup Type

Full Backups — Use when:

  • You need a standalone recovery point
  • Recovery time is more important than backup time
  • Storage is not a constraint
  • You’re establishing a new backup baseline

Full Backups — Do not use when:

  • Your database is very large (>10TB) and backup windows are tight
  • You’re doing incremental backup chains

Incremental Backups — Use when:

  • RPO targets are tight (under 1 hour)
  • Storage costs must be minimized
  • Backup window is limited

Incremental Backups — Do not use when:

  • Your backup chain complexity is a operational risk
  • You need faster recovery over storage savings

Differential Backups — Use when:

  • You need a middle ground between full and incremental
  • Restore simplicity matters but storage savings still appeal

Differential Backups — Do not use when:

  • Differential growth becomes nearly as large as a full backup
  • Your RPO requires more granular recovery

Backup Type Trade-offs

Dimension Full Backup Incremental Backup Differential Backup
Backup size Largest Smallest Grows over time
Backup speed Slowest Fastest Moderate
Restore complexity Simplest — one step Complex — chain required Moderate — full + one diff
Storage cost Highest Lowest Moderate
RTO (restore time) Lowest Highest Moderate
Best for Small DBs, baseline Large DBs, tight RPO Medium RPO, moderate complexity

Production Failure Scenarios

Failure Impact Mitigation
WAL gap from missed archive PITR restore impossible at exact point Monitor archive status continuously, alert on gaps
Backup chain corruption Full data loss — restore impossible Verify backup integrity on every job, store checksums
Storage exhaustion during backup Backup fails, disk fills Monitor disk space, alert at 70% threshold
Restore failing due to permissions DR procedure fails when needed most Test restore with minimal permissions weekly
Cloud snapshot restore taking hours Extended downtime exceeds RTO Pre-stage recovery environment, test RTO monthly
Incremental backup overflow Disk fills, backup deleted Set retention enforcement, monitor growth rate

Capacity Estimation: Backup Storage Sizing and WAL Growth Rate

Backup storage sizing depends on your backup strategy, retention period, and database growth rate.

Full backup storage formula:

full_backup_size = database_size × compression_factor
compressed_full_backup_size = database_size / compression_ratio

For a 500GB PostgreSQL database with pg_dump compression (typical ratio 3:1 to 5:1 for row data, less for indexes):

  • Row data with 3:1 compression: 500GB / 3 = ~167GB compressed dump
  • With gzip at 5:1: 500GB / 5 = 100GB compressed dump
  • Actual size varies significantly: highly compressible data (text, logs) compresses 10:1; binary data (JSON blobs) compresses 2:1

WAL growth rate formula:

WAL_daily_growth_bytes = measured_WAL_bytes_per_second × 86400

Measure WAL generation rather than inferring it from database write throughput. For example, 100MB/s of WAL generation is about 8.64TB per day before compression. wal_keep_size controls retained WAL for replication; it does not set the retention period for an external archive.

Incremental backup sizing: Track the change rate per day, not the total database size:

-- PostgreSQL: current WAL position since cluster initialization, not since checkpoint
SELECT
    pg_size_pretty(
        pg_wal_lsn_diff(pg_current_wal_lsn(), '0/00000000')::bigint
    ) AS wal_bytes_since_cluster_start;

Typical change rates: OLTP databases 1-5% of database size per day. Data warehouses with nightly batch loads: 20-50% per day during loads, 0% between loads. Knowing your change rate lets you size incremental backups correctly.

Observability Hooks: Backup Success/Failure Alerting and RTO Tracking

Key backup metrics: job success/failure, backup duration trends, restoration time, and backup size anomalies. The metric names below are examples from a site-specific exporter; map them to metrics your own collectors actually expose.

-- Track job duration and size using your backup tool's status/history command.

For PostgreSQL archiving, pg_stat_archiver exposes the last successful and failed archive attempts; it does not report end-to-end restore readiness.

# Critical: backup job failed
- alert: BackupJobFailed
  expr: backup_job_status != 0
  for: 1m
  labels:
    severity: critical
  annotations:
    summary: "Backup job {{ $labels.job }} failed: {{ $labels.error }}"

# Warning: backup duration increased significantly
- alert: BackupDurationAnomaly
  expr: backup_duration_seconds > 1.5 * avg_over_time(backup_duration_seconds[7d])
  for: 10m
  labels:
    severity: warning
  annotations:
    summary: "Backup taking {{ $value }}s vs typical {{ $labels.typical }}s"

# Warning: backup size anomaly (could indicate data growth or corruption)
- alert: BackupSizeAnomaly
  expr: backup_size_bytes > 2 * backup_size_bytes_offset_1d
  for: 1h
  labels:
    severity: warning
  annotations:
    summary: "Backup size {{ $value }} bytes is 2x yesterday's {{ $labels.yesterday }}"

# Critical: WAL archive failures (PITR at risk)
- alert: WalArchiveFailures
  expr: pg_archiver_failed_count > 0
  for: 5m
  labels:
    severity: critical
  annotations:
    summary: "PostgreSQL WAL archiving has failed; check archive health and PITR coverage"

Security and Compliance Notes

  • Confidentiality: Encrypt database backups, snapshots, and WAL archives in transit and at rest. Keep encryption keys and their recovery path separate from production database credentials; an encrypted backup is unusable if its key is lost.
  • Integrity and tamper resistance: Verify checksums before restoring, and keep an immutable or offline copy in a separate account or administrative boundary. Production credentials should not be able to alter or delete every recovery copy.
  • Access: Separate backup-write and restore permissions. Restrict destructive actions such as deleting snapshots or changing retention, require an approved break-glass path for them, and audit reads, restores, and policy changes.
  • Retention and recovery: Set retention and legal holds to match applicable data rules, including WAL archives and cross-region copies. Restore into an isolated recovery environment, verify the data and application before directing production traffic to it.

Quick Recap Checklist

Use this checklist when designing or reviewing backup and recovery for a database system:

  • Full backup completed and verified within last 24 hours
  • Incremental or differential backups scheduled based on RPO requirements
  • WAL archiving enabled and verified for PITR capability
  • Backup integrity verified via checksum validation after every job
  • Restore procedure tested in isolated environment within last 30 days
  • RTO and RPO documented and communicated to stakeholders
  • Cross-region backup copies exist for disaster recovery
  • Backup retention policy aligned with compliance requirements
  • Backup monitoring alerts configured for job failures and capacity
  • Recovery runbook documented with step-by-step restore procedures

Testing Recovery Procedures

Here’s the uncomfortable truth: a backup that cannot be restored is not a backup. This is non-negotiable.

Regular Recovery Testing

Weekly verification: Automated test restore to confirm backup chain validity.

#!/bin/bash
# Weekly backup verification script
set -euo pipefail

# Validate the latest physical base backup manifest. Set this path from your backup inventory.
pg_verifybackup /backups/latest

Monthly full disaster simulation: Complete restore to isolated environment, verify data integrity, measure actual RTO against targets.

What to Verify

Verification is not a single step. It is a chain of checks that must all pass before you trust a backup. Each stage catches different failure modes, and skipping any of them leaves a gap that only shows up during a real disaster.

Backup completion status confirms the job ran without errors. Check the exit code, the job log, and the backup size against expected ranges. A job that exits successfully but produces a 1KB file is not a successful backup — it is a false positive. Alert thresholds should trigger when backup size drops below 80% of the moving average.

Backup chain integrity validates that all required WAL segments are present and usable. Do not use pg_archivecleanup for verification; it deletes archived WAL that is older than the supplied restart point. Check the backup tool’s validation output and test recovery through the intended target time.

Restore completion means the backup actually restores without errors — not just that the backup command exits cleanly. For a pg_dump archive, pg_restore --list inspects its contents; for a physical base backup, use pg_verifybackup and perform a restore test. After restore, compare expected database contents and size against a known baseline.

Data integrity goes beyond row counts. Run checksum validation on critical tables, verify foreign key relationships, and spot-check high-value rows against known-good baseline values. Row count alone does not catch silent data corruption.

Application functionality testing happens after restore: run your application’s standard query suite against the restored database. If your app queries a specific customer record, query that record. If it aggregates daily totals, run that aggregation. This catches restore issues that only surface at the application layer.

Performance baseline establishes that restore does not degrade database performance. Measure query latency on the restored system before and after restore. If p99 query time doubles after restore, the backup is technically complete but operationally useless.

Common Recovery Failures

  • WAL gap: Missing WAL segments break the restore chain
  • Corrupted backup: Checksum failures on backup files
  • Storage exhaustion: Restore fails due to insufficient disk space
  • Permission issues: Restored database has wrong ownership
  • Timezone handling: Timestamps differ between backup and restore environments

Recovery During GitHub’s 2018 MySQL Incident

In October 2018, a network partition led GitHub’s MySQL clusters to accept writes in two data centers, leaving divergent data that could not be reconciled by a simple failback. GitHub chose a controlled recovery to protect data integrity. Restoring multi-terabyte backups from remote object storage and rebuilding replication took hours; GitHub said its backup procedure was tested daily, but this was the first time it had to rebuild an entire cluster from backup rather than rely on delayed replicas.

The incident illustrates two separate recovery questions: whether a backup can be restored, and how long a full restore takes under real conditions. GitHub’s postmortem describes the transfer, checksum, preparation, and load work involved in restoring large backups. GitHub’s incident analysis explains the failure and recovery timeline.

The lesson: keep tested backups and replicas with clear roles, and measure complete restore time instead of assuming it from a successful backup job.


Interview Questions

1. Your RPO is 15 minutes and your database writes 100GB/day. How do you design the backup strategy?

An RPO of 15 minutes means the latest recoverable point must be no more than 15 minutes behind the failure. Take regular base backups and archive WAL continuously, then monitor archive failures and recovery lag against that target. Measure WAL generation directly; total database write volume does not reliably predict it. PostgreSQL 17 and later support incremental base backups, but each still depends on its reference backup and a tested recovery chain. The backup schedule alone does not establish the achieved RPO.

2. During a restore, you discover the backup chain is broken — a differential backup references a WAL segment that was never archived. What happened and how do you recover?

A broken backup chain typically means WAL archiving failed silently — the backup tool reported success but the archive command did not actually copy WAL files. Recovery options depend on what you have: if you have the last full backup plus subsequent incremental backups, try to restore the latest full backup and replay available WAL. If PITR is impossible, you fall back to the last consistent state from the most recent complete backup. Root cause investigation: check archive_command logs for permission failures, disk space issues, or network timeouts. Mitigation: always verify WAL archive integrity immediately after backup, and monitor for gaps between expected and actual archived WAL sequence numbers.

3. Your team uses PostgreSQL and your boss asks why you can't just use `pg_dump` for backups. What are the trade-offs?

pg_dump creates a logical backup of a database that can be restored with `pg_restore` or `psql`, depending on format. It takes a consistent snapshot, but by itself it does not provide physical cluster recovery or PITR through WAL replay. For larger systems, physical base backups plus archived WAL can support PITR; logical dumps remain useful for portability, selective restore, and smaller databases. Choose based on tested restore time and recovery needs, not a fixed database-size cutoff.

4. How do you calculate realistic RTO for a 5TB database restoration across regions?

RTO = transfer time + restore time + WAL replay time + application cutover. At a sustained 100Mbps, transferring 5TB takes roughly 111 hours before protocol overhead; at 1Gbps it is roughly 11 hours. These are idealized estimates, so measure actual throughput and restore performance. If that exceeds the target, pre-position the data or maintain a standby in the recovery region.

5. What is the difference between PITR and point-in-time recovery, and why does the distinction matter?

PITR (Point-In-Time Recovery) is the capability — it means you can recover to any specific moment. Point-in-time recovery is the act of using that capability. The distinction matters because PITR requires WAL archiving (continuous backup of transaction logs). Without WAL archiving, you can only restore to the moment a full or incremental backup completed. With WAL archiving, you can replay logs to any timestamp within your WAL retention window. WAL archival must be configured before failure — you cannot enable it retroactively to recover from an already-happened failure.

6. Your backup job fails with "disk space exhausted" during a full backup of a 2TB database. How do you prevent this?

Prevention: never start a backup without verifying available disk space > 2× the expected backup size. Configure monitoring on backup destination: alert at 70% capacity, fail at 85%. For full backups of large databases, use compression (-Z flag in pg_basebackup) to reduce storage by 3-5×. Consider splitting full backups across multiple smaller volumes. If disk is already full during backup: cancel the backup job immediately to avoid corrupting the in-progress backup file, clean up old backups first, then restart. Some backup tools resume instead of restart — check your tooling. Long-term: implement backup rotation with retention limits enforced automatically.

7. A cloud provider experiences a regional outage and your production database is in that region. Walk through your recovery process.

Step 1: confirm the scope and estimated recovery time from the cloud provider. Step 2: activate DR environment in the alternate region if pre-positioned. Step 3: restore from latest cross-region backup if using backup-based DR. Step 4: if using read replica failover, promote the replica and update DNS. Step 5: verify data integrity — check last known good timestamp against application requirements. Step 6: notify stakeholders of RTO. Step 7: after primary region recovers, plan data reconciliation between DR and primary. The key DR principle: your RTO is only as good as your last tested recovery. If you have never tested restoring from cross-region backups, you do not know your actual RTO.

8. What is the difference between WAL shipping and streaming replication for PITR, and when would you choose each?

WAL shipping transfers archived WAL segments on a schedule; recovery lag depends on how often segments are archived and copied. Physical streaming replication sends WAL over a persistent connection and can keep a standby more current, though lag and failover time still depend on configuration and workload. Choose based on measured RPO/RTO, network reliability, and operational cost. A standby helps with availability, while a separate WAL archive supports longer-term PITR; neither replaces tested backups.

9. Your backup verification job reports success but the backup file is corrupted. What went wrong and how do you prevent it?

Backup verification must check completeness, not just completion. A backup job that exits with code 0 and creates a file is not verified — the file could be empty, truncated, or contain corrupted data. Prevention: validate the backup manifest or checksums, store validation metadata separately, and periodically perform a restore in an isolated environment. GitHub's 2018 incident shows that a tested backup can still take hours to restore at multi-terabyte scale. The lesson: a backup that cannot be restored is not a backup.

10. How does WAL segment accumulation cause storage issues, and what strategies control it?

Archived WAL is retained so it can be replayed during recovery; it is not consumed by normal PITR operations. High write volume or an archive destination problem can increase storage use or create an archiving backlog. Monitor archive failures and the age of the latest archived segment using your monitoring stack, set retention to cover the required recovery window, and test cleanup policies before they remove needed WAL. Compression can reduce storage use when supported by your backup tooling.

11. Your database writes 500GB/day and you have a 2-hour backup window. What backup strategy works?

500GB/day = ~6GB/hour write rate. A 2-hour backup window captures approximately 12GB of writes — much smaller than the full database if it is multi-terabyte. Strategy: weekly full backups (weekend or maintenance window) plus continuous WAL archiving for PITR, with incremental backups every 2 hours capturing only changed blocks. This gives you PITR capability (WAL replay to any point) without requiring full backups during the backup window. A two-hour backup window does not set the PITR RPO when WAL is archived continuously; measure archive lag and test recovery against the actual target. If RPO must be zero, use synchronous replication instead.

12. What are the trade-offs between backup replication to a separate region versus backup archival to object storage?

Replication to a separate region (e.g., cross-region RDS replica) provides fast failover (RTO minutes) and continuous data protection, but is expensive and replicates continuously. Backup archival to S3/Blob Storage is cheaper, provides point-in-time restore capability, but restore time is dominated by data transfer (hours for multi-TB databases). Best practice: use cross-region replication for HA/failover, and periodic backups to object storage for disaster recovery. This gives you both fast local failover and long-term point-in-time recovery. Never rely on a single backup strategy.

13. How do compression ratios affect your backup storage calculations, and why do estimates often differ from reality?

Backup storage formulas use compression ratios that vary significantly by data type. Text data (logs, JSON) compresses 5-10×. Row data with indexes compresses 2-3×. Binary data (images, encrypted blobs) compresses 1-1.5×. PostgreSQL TOAST data (large values stored separately) compresses well. Reality check: run pg_basebackup -F t -z -P on your actual database and measure the ratio. Budget for worst case (1.5×) and monitor actual ratios per environment. Production data grows over time — build in growth projections (typically 10-20% per year) when sizing backup storage.

14. Your organization performs quarterly disaster recovery testing. What metrics should you measure during the test?

Measure: actual RTO (time from DR initiation to database available), actual RPO (data loss measured in bytes or time), restore throughput (MB/s during restore), WAL replay time for the target point-in-time, DNS cutover time if applicable, and application reconnection time after failover. Document these against your documented RTO/RPO targets. The gap between documented and actual RTO/RPO is the most important finding. If actual RTO is 4 hours but you documented 1 hour, your SLA is wrong. Measure under realistic conditions — cold storage (Glacier) adds hours to restore time that you must account for.

15. A user accidentally drops a critical table at 3pm. You need point-in-time recovery to 2:59pm. Walk through the process.

Step 1: verify WAL archiving is enabled and continuous — check pg_stat_archiver. Step 2: confirm the latest full backup and all WAL segments after it are available. Restore the base backup to an isolated location, set restore_command and recovery_target_time = '2026-03-26 14:59:00 UTC' in postgresql.conf, and create an empty recovery.signal file in the data directory. Start PostgreSQL and verify the table and its data. Export the recovered table or validate the recovered cluster before directing any traffic to it. Current PostgreSQL versions use recovery.signal and settings in postgresql.conf, not recovery.conf. Total time depends on database size and WAL volume since last backup.

16. Your backup chain is intact but the most recent full backup failed verification. How do you recover?

If the most recent full backup fails verification, fall back to the previous full backup plus the incremental backups and WAL segments accumulated after it. This extends your RPO — you lose data from the failed backup window to the previous backup's time. Recovery: identify the last good full backup, restore it, replay all WAL segments since that backup, and verify the target point-in-time. Root cause the failed backup: disk errors, checksum mismatches, backup process bugs. Add additional verification steps to catch failures before the next DR scenario. Never skip the verification step assuming backups are good.

17. Under what conditions does streaming replication outperform backup/restore for disaster recovery?

Physical streaming replication can keep a standby close to the primary, with lag determined by workload and network conditions. Backup and restore can take hours for large databases, so a standby may better meet short failover targets. Replication does not protect against every user error because destructive changes can also reach the standby; use backups and WAL-based PITR for recovery to an earlier point. Choose the design based on tested recovery targets and the cost of maintaining a standby.

18. How does backup to tape versus disk affect your restore strategy, and what are the trade-offs?

Tape is cheaper per GB and good for long-term retention, but sequential access makes restore slow — to get to a specific point-in-time, you may need to restore multiple tapes in sequence. Disk is more expensive but provides random access — faster restore to any point in time, direct verification, and easier incremental management. Modern cloud backups (S3, Azure Blob) provide disk-like random access with tape-like cost economics when using infrequent access tiers. Recommendation: use disk or cloud for recovery-point backups (fast restore), use tape for long-term retention compliance. Never rely on tape alone for production recovery.

19. Your backup window is shrinking due to database growth. What options exist to maintain backup coverage?

Options: use incremental backups where supported by your PostgreSQL version and backup tool, tune compression and parallelism, reduce full-backup frequency only if tested WAL recovery still meets targets, or improve storage and network throughput. PostgreSQL 17+ `pg_basebackup` supports incrementals; `pg_backup_start`/`pg_backup_stop` define a backup operation but do not themselves create concurrent incremental streams. Re-measure duration as the database grows.

20. Your disaster recovery runbook is 10 pages long. How do you test it without causing a production outage?

Use an isolated environment that mirrors production: restore latest backup to the DR environment, verify data integrity matches production at a known point in time, practice the restore procedure in a sandbox, and measure actual RTO during the test. Automate as much of the runbook as possible — manual steps during a crisis cause delays. Run tabletop exercises where the team walks through the runbook without executing it. Reserve full DR tests (actual restore with downtime) for maintenance windows. Document discrepancies between the runbook and what actually happens during testing.


Further Reading


Conclusion

Backup and recovery is not a set-it-and-forget-it operation. It requires ongoing attention, testing, and refinement.

Start with the basics: full backups are non-negotiable. Layer on incremental or differential backups based on your RPO requirements. Enable WAL archiving if you need point-in-time recovery. Test everything—regularly.

The time to discover your backup strategy fails is not during an actual disaster. Run fire drills. Simulate failures. Know exactly what your RTO and RPO actually are under real conditions, not just on paper.

For deeper exploration of disaster recovery patterns, see our disaster recovery guide. And for monitoring your database health, check out relational databases fundamentals.

Category

Related Posts

Database Capacity Planning: A Practical Guide

Plan for growth before you hit walls. This guide covers growth forecasting, compute and storage sizing, IOPS requirements, and cloud vs on-prem decisions.

#database #capacity-planning #infrastructure

Failover Automation

Automatic failover patterns. Health checks, failure detection, split-brain prevention, and DNS TTL management during database failover.

#database #failover #high-availability

Disaster Recovery: RTO, RPO, and Building a Recovery Plan

Disaster recovery planning protects against catastrophic failures. Learn RTO/RPO metrics, backup strategies, and multi-region failover patterns.

#disaster-recovery #reliability #backup