Your backups open without us

Every backup is a standard dump, compressed with zstd and encrypted with age. With your key and free tools, you can restore it on your own machine, even if backupd is gone.

PostgreSQL 17 and later, restored with your key and nothing from us:

age -d -i backupd.agekey app.pgdump.zst.age | zstd -d \
  | pg_restore --no-owner --single-transaction -d "$TARGET_URL"

For servers from 9.2 to 16, pipe pg_restore’s script through psql instead; the docs give the line.

What you need

  • Your age key, added in Settings → Encryption.
  • The file, from Download encrypted or straight from your own bucket.
  • age, zstd, and your engine’s own restore tool.

Encryption

Every backup is compressed and encrypted with age before it’s stored. Add your own key to decrypt backups yourself.

Add key

Your keys

New backups are encrypted to every key here. Revoking a key only affects future backups.

  • Laptopage1lggyhqrw2nlhcxprm67z43rta597azn8gknawjehu9d9dl0jq3yqqvfafg3f9a1c0be47d2a85Added 2 Oct, 14:20Revoke
  • Ops team vaultage1zvkyg2lqzraa2lnjvqej32nkuu0ues2s82hzrye869xeexvn73equnujwjb81e07d95c42f3a0Added 2 Oct, 14:31Revoke

backupd’s key

backupd keeps its own key for this workspace so it can run restores and restore tests. Its secret half is encrypted at rest.

Service public keyage1qyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqs3290gq

Storage

2,317 backup files · 66.5 GB stored

FileSizeRestore testCreated
app-prod-2026-10-16-0900.pgdump.zst.ageapp-prod612 MBPassed12 min ago
billing-2026-10-16-0600.sql.zst.agebilling88 MBNot tested2 h ago
app-prod-2026-10-16-0800.pgdump.zst.ageapp-prod611 MBPassed1 h ago
events-2026-10-16-0300.archive.zst.ageevents1.4 GBPassed9 h ago
marketing-site-2026-10-13-0300.zip.agemarketing-site20 MBPassed3 days ago

Every file opens with Download encrypted, or straight from your own bucket.

Postgres

PostgreSQL 17 and later
age -d -i backupd.agekey app.pgdump.zst.age | zstd -d \
  | pg_restore --no-owner --single-transaction -d "$TARGET_URL"
PostgreSQL 9.2 to 16
age -d -i backupd.agekey app.pgdump.zst.age | zstd -d \
  | pg_restore --no-owner -f - | grep -v '^SET transaction_timeout' \
  | psql --single-transaction -v ON_ERROR_STOP=1 "$TARGET_URL"

MySQL and MariaDB

age -d -i backupd.agekey app.sql.zst.age | zstd -d \
  | mysql --defaults-extra-file=target.cnf target_db

MongoDB

Add --oplogReplay for a full replica-set backup
age -d -i backupd.agekey app.archive.zst.age | zstd -d \
  | mongorestore --archive --uri "$TARGET_URI"

Convex

age -d -i backupd.agekey app.zip.zst.age | zstd -d > snapshot.zip
npx convex import --replace-all snapshot.zip

What each file holds

Beside every backup sits a manifest, encrypted the same way, with the counts per table and the checksum of the dump. Decrypt it to check a file before you restore it:

Terminal

$ age -d -i backupd.agekey app-prod-2026-10-16-0900.pgdump.zst.age.manifest.age | jq .
{
  "version": 1,
  "createdAt": "2026-10-16T09:01:54.212Z",
  "format": "pg_custom",
  "codec": "zstd",
  "engineVersion": "16.4",
  "toolVersion": "pg_dump (PostgreSQL) 18.1",
  "tables": [
    { "schema": "public", "name": "sessions", "rows": 1402377, "exact": true },
    { "schema": "public", "name": "orders", "rows": 96512, "exact": true }
  ],
  "plaintextBytes": 3113851904,
  "plaintextSha256": "9c1f…e07a",
  "storedBytes": 641728512,
  "storedSha256": "5b3d…41c2"
}

Add your key first

A key added today opens every backup made after it. Starter is free for 14 days.