Restore to a point in time
Goal: Bring a database back to the state it was in at a specific moment in the past — useful for recovering from accidental deletes, bad migrations, or data corruption.
Prerequisites:
- A Pro or Business project with a dedicated managed Postgres.
- A target timestamp within the retention window (Pro: last 30 days, Business: last 90 days, minus a small lag buffer on both ends).
PITR is Pro+ only. Hobby and Dev tiers do not support point-in-time recovery — requests are rejected with 403 tier_required.
How it works
Section titled “How it works”Requesting a restore does not touch your live database. uploy creates a parallel cluster from the archived base backup plus WAL replay up to your chosen timestamp. Once it’s ready, you decide:
- Promote — the parallel cluster becomes the live database. The injected
DATABASE_URLis rewritten; your apps reconnect automatically. The previous cluster is deleted. - Discard — the parallel cluster is deleted; your live database is unchanged.
Only one restore can be pending per database at a time.
- Open the project → Database tab → the database you want to restore.
- Click Restore. A dialog opens.
- Choose Point in time.
- Pick a timestamp. The date/time picker’s
minandmaxare bound to your tier’s valid window; anything outside returns400 invalid_timestamp. - Click Submit.
- A Restore pending banner appears. It shows when you requested the restore and the name of the parallel cluster being built. Wait for the parallel cluster to become ready (typically a few minutes).
- When ready, the banner offers two buttons:
- Promote — you are prompted to confirm. Clicking Continue swaps in the restored cluster. Apps reconnect on their next database request.
- Discard — deletes the parallel cluster. Your live database is untouched.
Verify
Section titled “Verify”- After Promote: the database’s cluster name in the UI reflects the restored cluster, and the Restore pending banner disappears. Your app’s logs show it reconnecting to the database.
- After Discard: the banner disappears; nothing else changes.
Picking a good timestamp
Section titled “Picking a good timestamp”- The window starts one hour after the oldest base backup (buffer for base-backup lag).
- The window ends one minute before the current time (buffer for WAL archival lag).
- If the exact moment matters (e.g. right before a bad migration), pick a time just before the incident; you can always request another restore if you overshoot.
Limits
Section titled “Limits”- One pending restore per database. Requesting a second one while the first is pending returns
409 restore_pending. - Retention determines the earliest point you can reach: 30 days on Pro, 90 days on Business.
- Promote is destructive with respect to writes that happened after your chosen timestamp — they are not preserved. Download a backup or take an application-level snapshot first if you want to keep them.
Troubleshooting
Section titled “Troubleshooting”If the restore-pending banner doesn’t progress to a ready state, see Restore stuck in pending.
Next steps
Section titled “Next steps”- Download a backup — Hobby-only artifact download.
- Managed Postgres reference — retention and tier details.