# How a backup works (/docs/backups)

Every backup, scheduled or manual, goes through the same steps.

<Steps>
<Step>

### Connect [#connect]

backupd resolves your database's host, checks that it is a public address, and connects over TLS with the credentials you saved. They are passed to the dump tool through the environment or a private file that is deleted after the run, never on a command line.

</Step>
<Step>

### Dump with the engine's own tool [#dump-with-the-engines-own-tool]

| Engine | Tool | Format |
| --- | --- | --- |
| PostgreSQL | `pg_dump`, on an exported snapshot | Custom format (`.pgdump`) |
| MySQL, MariaDB | `mysqldump --single-transaction` | SQL (`.sql`) |
| MongoDB | `mongodump --archive`, with `--oplog` for replica sets | Archive (`.archive`) |
| Convex | `convex export`, file storage included | ZIP (`.zip`) |

Row or document counts are taken as the data is dumped, so the backup knows exactly what it holds.

</Step>
<Step>

### Compress and encrypt on the way [#compress-and-encrypt-on-the-way]

The dump is compressed with zstd and encrypted with age as it streams to backupd Storage. It is encrypted to backupd's key for your workspace and to every key you have added in **Settings → Encryption**. Storage only ever holds the encrypted file.

PostgreSQL, MySQL and MongoDB dumps stream straight through. A Convex export is staged on a temporary disk first, then compressed and encrypted.

</Step>
<Step>

### Write the manifest [#write-the-manifest]

Next to every backup, backupd stores a small [manifest](/docs/restoring/manifest), encrypted the same way, with the table counts and checksums.

</Step>
<Step>

### Check the stored file [#check-the-stored-file]

The stored file is read back, decrypted and decompressed, and both checksums are compared. Then, on your plan's cadence, the backup is restored into a sandbox. See [Integrity checks and restore tests](/docs/backups/verification).

</Step>
<Step>

### Copy to your bucket [#copy-to-your-bucket]

On Pro, the encrypted file and its manifest are copied byte for byte to each of [your own buckets](/docs/storage/destinations).

</Step>
</Steps>

## Progress and status [#progress-and-status]

A running backup shows its phase: **Queued**, **Connecting**, **Backing up**, **Uploading**, **Finishing** and **Verifying**. When it is done, it is marked as succeeded or failed, and its restore test result is shown as **Verified**, **Verifying**, **Unverified** or **Restore failed**.

## Plan limits [#plan-limits]

|                                           | Starter | Pro     |
| ----------------------------------------- | ------- | ------- |
| Backups running at once (whole workspace) | 2       | 4       |
| Longest run                               | 3 hours | 6 hours |
| Largest backup (stored size)              | 50 GB   | 100 GB  |
| Manual backups per database per day       | 12      | 48      |

If more backups are due than your plan runs at once, the rest wait in the queue. A backup that runs longer than the plan's limit is stopped and fails with _The backup ran longer than this plan's 3 h limit_. A backup whose stored file grows past the largest backup size is stopped too. Before reading anything, backupd refuses a database that clearly won't fit, with a message like _This database (~120 GB) won't fit in the 100 GB this backup may use_.

## Retries [#retries]

Temporary problems are retried automatically: the database being unreachable, a lock held by a schema change, a dump that stalled, or a storage error. While a backup waits to retry, its message starts with _Retrying:_. You are alerted with **Backup failed** only when the last attempt fails.

Problems that won't fix themselves, such as rejected credentials, a missing privilege, an unsupported version or an invalid connection string, fail straight away. See [Backup failures](/docs/troubleshooting/backup-failures).

## Every backup is a full copy [#every-backup-is-a-full-copy]

backupd doesn't offer point-in-time recovery or incremental backups yet. Every backup is a complete, self-contained dump that you can restore on its own.
