MySQL and MariaDB backups, no locks

backupd runs mysqldump in a single transaction on your schedule, keeps your routines, triggers and events, and restores each backup into a sandbox to count every table’s rows.

Restore test

billing-2026-10-16-0600.sql.zst.age
Restorable
Tables
5 of 5
Rows
1,051,004
Took
26s
Sandbox
mysql 8.4
  1. Fetch the backup88 MB from storage2s
  2. DecryptUnlocked and checksum matched1s
  3. RestoreInto a temporary MySQL database19s
  4. Count rowsEvery table matches the backup3s
  5. Clean upTemporary database dropped1s
Counts per table, backed up against restored
TableBacked upRestoredResult
invoice_lines804,112804,112match
invoices212,950212,950match
customers31,40831,408match
plans2,1162,116match
coupons418418match
5.7+
MySQL 5.7+ and MariaDB 10.3+.
No locks
One consistent transaction, no table locks.
Whole schema
Routines, triggers and events included.
Exact counts
Rows counted exactly, every table.

How a backup runs

  1. Dump in one transactionmysqldump runs in one transaction with your routines, triggers and events. We count every table’s rows from the dump as it is written.
  2. Compress and encrypt on the wayThe dump is compressed with zstd and encrypted with age as it streams to storage in 64 MiB parts. Nothing is written to a disk on the way.
  3. Check the file we storedThe stored file is read back, decrypted and decompressed, and both checksums are compared before the backup counts as good.

Backup

billing-2026-10-16-0600.sql.zst.age
Succeeded
  1. Dumpmysqldump --single-transaction
  2. Compresszstd, 540 MB to 88 MB
  3. Encryptage, to 3 keys
  4. Upload2 parts of 64 MiB, nothing on disk
  5. CheckRead back, both checksums match

Took 47s · Scheduled

The restore test

On your plan’s cadence, the backup is loaded into a temporary database on a sandbox MySQL server.

Every table’s rows are counted and compared with the counts taken from the dump itself, which are exact for every table. Then the temporary database is dropped.

How restore tests work

What backupd needs

  • A mysql:// connection string with the database name in it. One database per connection.
  • TLS is required: ssl-mode REQUIRED, VERIFY_CA or VERIFY_IDENTITY.
  • A read-only user is enough to back up.
  • Credentials go to mysqldump in a private option file, never on the command line, and the file is deleted after the run.

Add database

backupd connects over TLS. Use a read-only user.

Connection string

mysql://backup:••••@db.example.com:3306/billing

Schedule

Every 6 hours

Keep backups

30 days

CancelTest and add

Restore it yourself

Every backup is encrypted with age to your key as well as ours. Download it, and open it with free tools on your own machine:

Terminal

# Decrypt, decompress and load into any database
$ age -d -i backupd.agekey app.sql.zst.age | zstd -d \
  | mysql --defaults-extra-file=target.cnf target_db

Restoring without backupd

Not yet

  • One database per connection string. Add each database you want backed up.
  • Tablespaces are not dumped, and GTID state is not written to the dump, so it restores into any server.
  • Point-in-time recovery and incremental backups are not available yet; every backup is a full copy.
  • Private networks and SSH tunnels are not supported yet.

Questions

No. mysqldump runs with --single-transaction and --skip-lock-tables, so InnoDB tables are read from one consistent snapshot while your app keeps writing.

Yes. backupd detects MariaDB from the server version and supports 10.3 and later.

In-app restores strip DEFINER clauses, so you don’t need SUPER or the original accounts on the target.

Back up MySQL and MariaDB tonight

Paste a connection string, pick a schedule and add your key. Starter is free for 14 days.