Skip to content

Backups

Pier backs up databases by dumping them inside the running container, compressing the output, and shipping it to object storage. Backups are configured per service and run on a cron schedule, with retention enforced after every successful run.

Backups are available for PostgreSQL (including PostGIS and TimescaleDB), MySQL, MariaDB and MongoDB. Each engine produces a different on-disk format:

EngineDump toolStored format
PostgreSQL / PostGIS / TimescaleDBpg_dump -Fc (custom format).dump (self-compressed)
MySQL / MariaDBmysqldump.sql.gz (gzipped in Pier)
MongoDBmongodump --archive --gzip.archive.gz

PostgreSQL dumps always run as the cluster superuser so extension schemas (e.g. PostGIS tiger/topology) are captured cleanly.

A schedule with a database_name set backs up a single logical database. A schedule with no database name is cluster-wide: for SQL engines it loops over every database it knows about and bundles them into a single .tar.gz (entries named <db>.dump or <db>.sql); for MongoDB it runs one full-instance mongodump.

Restore is per-database only. Cluster-wide tar archives are supported as a source — Pier extracts the one database you’re restoring into — but you can’t restore a whole cluster in one action.

Each schedule stores a cron expression, a retention count and the target S3 storage. Defaults when you create one:

FieldDefault
Cron0 2 * * * (daily at 02:00)
Retention7 backups kept

Schedules are driven by the unified scheduler (see Scheduled tasks) — a backup schedule appears in the Schedules list as a backup action. You can also trigger an ad-hoc run at any time; an ad-hoc per-database run falls back to the cluster-wide schedule’s storage if no per-database schedule exists yet.

Backups upload to S3-compatible object storage or to Bunny.net. A storage entry holds the endpoint, region, bucket, access key, secret key and an optional key prefix (default pier-backups). Keys are laid out as {prefix}/{service}/{filename}. Use Test to verify the connection before pointing a schedule at it.

After each successful backup, Pier keeps the newest retention_count completed backups for that schedule and deletes the rest — both the object-storage blob and the database record. A failed cleanup is logged but never fails the backup itself.

There are two restore paths, both per-database and both destructive — the target database is dropped and recreated, so the target must already exist in the service (its stored credentials supply the owner role and password):

  • Restore from a stored backup — downloads the blob from storage, extracts the database from a cluster tar if needed, and replays it via pg_restore/psql/mysql/mongorestore.
  • Restore from a direct upload — upload a .dump, .sql.gz, .tar.gz or .archive.gz file by hand. This is the cross-cluster disaster-recovery path: it works on a fresh Pier instance with no storage configured. The format is detected from the filename and validated against the target engine.

Backups can also be downloaded as files and deleted individually.

Independently of database backups, Pier takes a daily local snapshot of its own state: pier.db and .env are copied into data/backups/system/, timestamped per day, with the last 7 days retained. This protects the control-plane database and encryption configuration; it is not shipped offsite.