Point-In-Time Recovery for your Postgres database. Continuous WAL archiving to S3-compatible storage means you can restore to any second in history — not just the last snapshot.
# Check current PITR configuration
nself pitr status
# Enable WAL archiving (requires S3-compatible bucket config in env)
nself pitr enable
# Verify the archive pipeline is healthy
nself pitr testnself pitr <SUBCOMMAND> [FLAGS]nself pitr configures continuous WAL (Write-Ahead Log) archiving from your Postgres instance to any S3-compatible object storage — AWS S3, MinIO, Cloudflare R2, Backblaze B2, and others. WAL segments are shipped in near real-time (typically under 60 seconds lag). Combined with periodic base backups, this gives you the ability to restore to any point in time within your retention window.
Restoration happens into an isolated sidecar container so your production database is never touched during a restore operation. Once the recovery container reaches the target timestamp, you validate the data before promoting it to replace the primary.
Before enabling PITR, set the following env vars:
nself env set PITR_S3_ENDPOINT https://s3.amazonaws.com # or your R2/MinIO endpoint
nself env set PITR_S3_BUCKET my-nself-wal-archive
nself env set PITR_S3_REGION us-east-1
nself env set PITR_S3_KEY_ID AKIAIOSFODNN7EXAMPLE
nself env set PITR_S3_SECRET wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEYShow the current PITR configuration: whether archiving is enabled, the archive endpoint, lag, retention period, and the oldest recoverable point.
nself pitr status
# PITR: enabled
# Archive endpoint: s3://my-nself-wal-archive (us-east-1)
# WAL lag: 12 seconds
# Retention: 30 days
# Oldest recovery: 2026-04-07T08:22:00Z
# Last base backup: 2026-05-06T03:00:00Z (24 hours ago)Enable WAL archiving. Validates S3 credentials, configures archive_command in Postgres, and schedules a base backup immediately.
nself pitr enable
# Validating S3 credentials... ✓
# Setting archive_command... ✓
# Reloading PostgreSQL config... ✓
# Taking initial base backup... ✓ (completed in 8s)
# ✓ PITR enabled. WAL archiving is now active.Set a custom retention window (default: 30 days):
nself pitr enable --retention 14dVerify the end-to-end archive pipeline without touching production data. Writes a test WAL segment, confirms it arrives in the S3 bucket, and measures lag.
nself pitr test
# Writing test WAL segment... ✓
# Waiting for archive upload... ✓ (lag: 8s)
# Verifying segment in S3... ✓
# PITR pipeline is healthyRestore the database to a specific point in time. Spins up an isolated recovery container, applies WAL segments up to the target timestamp, then pauses for validation before promotion.
# Interactive restore (prompts for target time)
nself pitr restore
# Restore to a specific timestamp (ISO 8601)
nself pitr restore --to 2026-05-07T10:30:00Z
# Restore and auto-promote after validation (production use requires --confirm)
nself pitr restore --to 2026-05-07T10:30:00Z --auto-promote --confirmThe restore flow:
localhost:5433# Inspect the recovered data before promoting
psql -h localhost -p 5433 -U postgres -c "SELECT count(*) FROM np_users;"
# Promote the recovery container to replace the primary
nself pitr restore --promote
# OR discard without promoting
nself pitr restore --discardTake a base backup immediately and upload it to S3. Base backups are taken automatically on a schedule (default: daily at 03:00 UTC), but you can trigger one manually.
nself pitr backup-sync
# Starting base backup...
# Uploading to s3://my-nself-wal-archive/base/2026-05-07T14-22-00/
# ✓ Base backup complete (1.2 GB, 14s)List all base backups in the archive bucket with their size and age.
nself pitr backup-sync-status
# TIMESTAMP SIZE AGE
# 2026-05-07T03:00:00Z 1.2 GB 11 hours
# 2026-05-06T03:00:00Z 1.1 GB 35 hours
# 2026-05-05T03:00:00Z 1.1 GB 59 hoursRun a non-destructive restore drill — spins up a recovery container, restores to the most recent recoverable point, validates basic database health, then tears down the container. Used for routine DR testing.
nself pitr restore-drill
# Locating latest base backup... ✓
# Starting recovery container... ✓
# Applying WAL to latest point... ✓ (lag: 18s)
# Running health checks... ✓
# Tables accessible: 47/47
# Tearing down recovery container... ✓
# ✓ Restore drill passed (total: 2m 14s)List the results of previous restore drills with timestamps and pass/fail status.
nself pitr restore-drill-list
# TIMESTAMP RESULT DURATION WAL LAG
# 2026-05-07T04:00:00Z PASS 2m 14s 18s
# 2026-05-06T04:00:00Z PASS 2m 09s 22s
# 2026-05-04T04:00:00Z FAIL — timeout| Flag | Applies to | Type | Description |
|---|---|---|---|
--retention | enable | string | WAL retention window, e.g. 7d, 30d (default: 30d) |
--to | restore | string | ISO 8601 target recovery timestamp |
--auto-promote | restore | bool | Promote automatically after recovery (requires --confirm) |
--confirm | restore | bool | Confirm destructive promotion without interactive prompt |
--promote | restore | bool | Promote a paused recovery container |
--discard | restore | bool | Tear down a paused recovery container without promoting |
--json | status, backup-sync-status, restore-drill-list | bool | JSON output |
| Variable | Description |
|---|---|
PITR_S3_ENDPOINT | S3-compatible endpoint URL |
PITR_S3_BUCKET | Bucket name for WAL archives and base backups |
PITR_S3_REGION | Bucket region |
PITR_S3_KEY_ID | Access key ID |
PITR_S3_SECRET | Secret access key |
PITR_BACKUP_SCHEDULE | Cron expression for base backup schedule (default: 0 3 * * *) |
PITR_DRILL_SCHEDULE | Cron expression for automated restore drills (default: 0 4 * * *) |