Database backups & restore
Automatic daily backups, continuous WAL archiving, point-in-time recovery, and the three ways to restore a managed PostgreSQL database.
Every managed database is backed up automatically — there is nothing to enable.
- Daily base backups. A full
pg_basebackupof the database is taken once a day and stored off-host in object storage. - Continuous WAL archiving. Every write-ahead-log segment is archived as it is produced, so the recoverable history is continuous — not just daily snapshots.
Together these give point-in-time recovery (PITR): you can restore the database to any moment inside your retention window, not only to the moments a backup happened to run.
Retention by plan
| Plan | PITR window |
|---|---|
| Free | 7 days |
| Pro | 30 days |
| Team / Enterprise | 90 days |
Backups older than the window are pruned automatically (the newest backup is always kept, and pruning is PITR-safe: the window's full depth stays restorable). Deleting a database also deletes all of its backups.
The dashboard shows your effective window on the database's Backups & restore tab, or fetch it from the API:
curl https://api.pandastack.ai/v1/databases/{id}/backups \
-H "Authorization: Bearer $PANDASTACK_API_KEY"Three ways to restore
1. Restore in place — same database, same connection string
Rolls this database back to a point in time. The id, host, and connection string — including the password — are preserved, so nothing that connects to the database needs re-pointing.
curl -X POST https://api.pandastack.ai/v1/databases/{id}/restore \
-H "Authorization: Bearer $PANDASTACK_API_KEY" \
-H "Content-Type: application/json" \
-d '{"target_time":"2026-08-20T14:00:00Z"}'Omit target_time to restore to the latest archived state. The call returns
202 and the rebuild runs in the background — poll GET /v1/databases/{id}
until it reports running.
In-place restore is undoable. Before anything is overwritten, a fresh safety backup of the current state is taken — so if you restored to the wrong moment, restore again to just before the first restore.
Requirements: the database must be running, and target_time must be at
least 2 minutes in the past and inside your retention window.
2. Clone — a new database, original untouched
Provisions a brand-new database (new id, new connection string) from this database's backups, optionally at a point in time. The source keeps running unaffected — ideal for inspecting old data, staging a migration, or branching.
curl -X POST https://api.pandastack.ai/v1/databases/{id}/clone \
-H "Authorization: Bearer $PANDASTACK_API_KEY" \
-H "Content-Type: application/json" \
-d '{"label":"my-db (investigate)","target_time":"2026-08-20T14:00:00Z"}'A clone can also change RAM tier via size — this is the supported "resize"
path.
3. Failover — rebuild a dead database
If a database's host is lost, POST /v1/databases/{id}/failover rebuilds it on
a healthy machine from the archive (same id; the password rotates). The
dashboard offers this automatically when a database reports failed.
Choosing
| Restore in place | Clone | Failover | |
|---|---|---|---|
| Use when | "Undo bad writes" | "Look at old data safely" | Database is dead |
| Target | This database | A new database | This database |
| Connection string | Unchanged | New | Same host, new password |
| Original data | Overwritten (after a safety backup) | Untouched | Already lost |
Backup health
You don't have to trust that backups are working — the platform verifies its
own archive and tells you. A background scrubber checks each database's chain
(base backups present and sane, WAL segments continuous with no gaps) and the
result is surfaced on GET /v1/databases/{id}/backups:
{
"health": {
"status": "ok",
"detail": "",
"checked_at": "2026-08-21T10:12:00Z"
}
}status is ok, warn, or error, with detail explaining anything found
(for example a WAL gap on the live timeline, or a zero-size base backup). If
health reports a problem you didn't cause,
contact support — don't wait until you need a
restore to find out.