Guides

Backups & restore

Back up your databases and service data on a schedule, keep the copies you need, and restore one with the step-by-step wizard, from the panel or the terminal.

A backup is a spare copy of your data kept somewhere else, so that if today's copy is lost or broken you can go back to a good one. Synq does three jobs here:

  • it copies your data to a storage place you choose, a destination;
  • it does that on a schedule, following a policy, and prunes old copies;
  • when you need it, it puts a copy back with a restore.

This page covers databases and services. For a single named volume, see Volumes & volume backups.

What you need first

  • A project with at least one service that holds data, such as a database added from the catalog or a Compose db service.
  • A backup destination: an S3-compatible bucket, an SFTP or FTP host, Dropbox, Google Drive, one of your servers, or a local folder. Add it once under Backups in the sidebar; see Backup destinations.

What gets backed up

The Backup method of a policy decides what one backup contains. Auto is the default and does the right thing for most services.

MethodWhat it capturesRestore
AutoPicks per service: a database dump for a recognised database image, otherwise a snapshot of the service's volumes. The editor tells you what it detected and the method Auto will use (for PostgreSQL, pg_dump).As for the method it picked.
DatabaseA logical dump taken inside the running service: pg_dump (PostgreSQL, PostGIS), mysqldump (MySQL, MariaDB, Percona), mongodump (MongoDB) or an RDB snapshot (Redis, Valkey). Consistent as of the moment it starts, and restorable into a newer version.Written back through the running database.
VolumeA tar of the service's volumes and bind mounts, taken live.The service is stopped, the volumes are replaced, the service starts again.
FilesOnly the folders you name, archived from inside the running service.Extracted back into those folders.
CustomThe output of your own Dump command, run inside the container.Fed to your Restore command on standard input.

A database is recognised by its image name: postgres, postgis/postgis, mysql, mariadb, percona/percona-server, mongo, percona/percona-server-mongodb, redis, redis/... or valkey/valkey. For a custom-built image, choose Database and pick the Engine yourself.

Step 1: set a backup policy

A policy says: back this up, to that destination, on this schedule, and keep this many copies.

Open the project's Backup tab

Open the project and choose Backup. You see Backup destinations (with Manage to add more), Services + policies, and Recent backups.

Choose what the policy covers

  • Project-level policy: one policy that backs up every service of the project. Press Create policy on its row.
  • A single service: press Create policy on that service's row. You can also do this from the service itself: Apps & Services → the service → Backup.

If Create policy is greyed out, there's no destination yet (Add a destination first).

A single app with no services has no policy rows here. Keep its data in a named volume and back that up with a volume backup.

Fill in the policy

  • Destination: where the copies go. Add new destination opens the destination form without leaving the editor.
  • Schedule: Hourly, Daily (03:17), Weekly (Sun 03:17), Monthly (1st 03:17), Manual only, or your own five-field cron expression (for example 0 2 * * * for 02:00 every day). Manual only never runs on its own.
  • Retain count: keep the N most recent successful backups. Retain days: drop backups older than N days. Use either, both, or neither (Unlimited).
  • Backup method: see the table above. Each method shows its own options:
    • Database: Engine, to force a dump tool.
    • Files: Folders to archive (one absolute path per line) and Replace on restore (empty the folder before extracting; refused for system and top-level folders).
    • Volume: Volumes to include (blank means all), Pause while copying (freezes the service for a consistent copy; it's unavailable until the copy finishes) and Exclude patterns such as ./cache or *.sock.
    • Custom: Dump command and Restore command. The restore command is required; without it a backup could never be restored.
    • Compression: zstd (smallest), gzip (works without any download, for air-gapped servers) or none. Auto uses what the service has.

Optional: Advanced options

Open Advanced options for:

  • Pre-deploy trigger: also back up automatically right before each new deployment goes live. Your safety net for bad deploys and migrations.
  • Webhook trigger: creates a private token so an outside scheduler or CI job can start this backup (see Trigger a backup from outside). Rotate token replaces it.
  • Pre-hook (runs before snapshot): a shell command run first. It can produce what gets backed up, for example pg_dump > /tmp/dump/db.sql followed by a Files backup of /tmp/dump. If it fails, the run is aborted, so a stale copy is never saved as if it were fresh.
  • Post-hook (runs after upload): cleanup. Its failure is logged but doesn't fail the run.

Check the Summary, keep Policy enabled ticked, and press Create policy.

Retention runs after each successful backup, separately for each service in a project-level policy. Protected copies are skipped (Step 3). If cleanup fails, the records are kept and retried; the new backup is still valid. The Backup retention prune system job is a fallback; new installations run it every hour at minute 29, and you can change it under Jobs.

Step 2: run a backup now

You don't have to wait for the schedule. Any service or project policy row has Backup now. It asks for an optional Name, for example Before the v2 migration, so you can find this copy later; leave it empty for an unnamed run. A name is up to 80 characters of letters (any language), digits, spaces and - _ . : ( ) # @ + , /. Extra spaces are collapsed, and a name with any other character is refused rather than changed. Press Run backup. A Live backup card appears with real-time progress; the backup runs on the server, so it keeps going if you close the tab. When it finishes, the run appears in Recent backups (the 25 most recent runs of the project) with its name, status and size. The name is also written into the backup's manifest.json at the destination.

Over the API, send the name in the body: POST /api/backup-policies/<policyId>/run with {"name": "Before the v2 migration"}. The body is optional.

Step 3: protect a copy from pruning

Retention deletes old copies automatically. To keep one no matter what (say, the last good state before a big change), press the lock icon on the run in Recent backups (Protect from retention). It gets a Protected badge and pruning skips it. Press it again (Allow retention to prune) to release it.

Step 4: restore a backup

A restore puts a saved copy back in place of the current data. It overwrites what's there now, so Synq walks you through it in steps.

Start

In Recent backups, find a successful run and press its Restore icon (Restore from this backup). The Restore backup wizard opens. Its steps are Review, Prepare, Confirm, Apply and Done.

Review

The first screen shows the backup's date, size and number of artifacts, and warns This will overwrite current data. Leave Protect the latest backup from retention prune ticked (the default): it keeps the most recent successful backup safe from automatic deletion, so you can go back to "right before this restore". Press Continue → Prepare.

Prepare

Synq checks that the backup's files exist at the destination and are intact (Verifying backup...). Nothing is changed yet; the service keeps running. When it's done: Backup verified, ready to apply.

Confirm

Type the service name exactly (for a volume backup, the volume name). This is the "are you really sure?" gate, because the next step replaces the current data. Press Apply restore.

Apply

For a volume or files backup, the service stops briefly while the data is swapped, then starts again. A database dump is written back through the running database (Redis applies it after a restart). Keep the window open until it says Restore complete.

Take a fresh backup first

Synq does not back up the current state for you before a restore. The protect tick only shields a backup that already exists. If you might want today's data back, press Backup now before you start the restore.

Cancelling a restore

  • Before anything is written, Cancel (on Review) or Cancel restore (while preparing) leaves your data exactly as it was.
  • During Apply, Abort restore asks for confirmation. Once data is being written, aborting leaves the target with partial data and the service is deliberately left stopped. Run the same restore (or a newer one) to completion before starting it again.

Trigger a backup from outside

With Webhook trigger on, a policy has a token. Start the backup from anywhere that can make an HTTPS request, with the token as a bearer token:

curl -X POST -H "Authorization: Bearer $BACKUP_WEBHOOK_TOKEN" \
  "$SYNQ_URL/api/webhooks/backup"

The token is the last part of the URL the policy editor shows. The response contains the new runId. SYNQ_URL is your panel address (for example https://app.example.com).

CLI

The base command is synq backup, with the groups destination, policy, run and restore.

# 1. Add a destination (S3-compatible example) and verify it
synq backup destination create \
  --name "Production R2" --kind s3_compatible \
  --endpoint https://<account>.r2.cloudflarestorage.com \
  --bucket my-backups --region auto \
  --access-key-id <id> --secret-access-key <key>

synq backup destination list
synq backup destination preflight <destinationId>

# 2. A daily policy for one service, keeping 7 copies, also before each deploy
synq backup policy create \
  --project <projectId> --destination <destinationId> \
  --service <serviceId> --cron "0 3 * * *" \
  --retain-count 7 --pre-deploy

# ...or one project-level policy for every service (leave out --service)
synq backup policy create --project <projectId> --destination <destinationId> --cron "0 3 * * *"

# 3. Run it now and watch it finish
synq backup policy run <policyId> --follow

# 4. See runs, and protect one from pruning
synq backup run list --project <projectId>
synq backup run protect <runId>            # or --release to unprotect

# 5. Restore, deliberately in two steps
synq backup run restore <runId>            # prepares it, prints a restoreId and a token
synq backup restore apply <restoreId> --token <confirmationToken> --follow

--payload-kind chooses the method (auto, pg_dump, mysql_dump, mongo_dump, redis_rdb, volume, path, custom_command), and --payload-config takes its options as JSON.

Restore is deliberately two steps

backup run restore only prepares the restore and hands you a confirmation token; nothing changes yet. backup restore apply with that token swaps the data in. This mirrors the "type the name" gate in the panel.

Troubleshooting

A destination won't verify

Press Verify connection on the Backups page and read the reason. The usual causes are a wrong key or password, a bucket or folder that doesn't exist, or a host or port that isn't reachable.

Create policy is greyed out

There's no destination yet. Add and verify one under Backups, then come back to the project's Backup tab.

Auto made a volume snapshot of my database

Auto uses a dump only when it recognises the image and the service has a running container. For a custom image, choose Database and set the Engine. Check the Summary before saving.

A backup run failed

Open it in Recent backups; a failed run shows its error. A failing pre-hook aborts the run on purpose (for example a pg_dump that can't connect), so the copy is never half-made.

I need to undo a restore

There is no one-click undo. Restore again from the backup taken before the restore (the one you protected, or the one Backup now made).

On this page