Back up your PostgreSQL database and ENCRYPTION_KEY, restore from a dump or Docker volume snapshot, and automate daily backups with a cron script.
All Breadbox data — accounts, transactions, bank connections, categories, rules, and users — lives in PostgreSQL. To protect your data, you need two things: a regular database backup and a secure copy of your ENCRYPTION_KEY.
All financial data — accounts, transactions, connections
ENCRYPTION_KEY
Your .env / .docker.env file or secrets store
Access to bank connections (transactions stay, but connections can’t sync)
Back up both. A database backup without the matching encryption key leaves your transaction history readable but all bank connections broken — you’d need to re-link every account.
Never lose your ENCRYPTION_KEY. Breadbox uses AES-256-GCM to encrypt Plaid and Teller access tokens at rest. If the key is lost, there is no way to decrypt the stored credentials. Store the key in a password manager or secrets vault, separately from your database backup.
pg_dump is the most reliable way to back up a running PostgreSQL database. The custom format (-Fc) produces a compressed archive you can restore selectively.
--clean --if-exists drops existing objects before recreating them, making the restore idempotent.
3
Restart Breadbox
docker compose start breadbox
4
Verify the restore
Check that data came back by querying key tables:
SELECT 'users' AS table_name, COUNT(*) FROM usersUNION ALLSELECT 'bank_connections', COUNT(*) FROM bank_connectionsUNION ALLSELECT 'accounts', COUNT(*) FROM accountsUNION ALLSELECT 'transactions', COUNT(*) FROM transactions;
Then sign in to the admin dashboard and confirm that connections show their last sync time and status.
If you run Breadbox with Docker Compose, PostgreSQL data lives in the breadbox_postgres_data named volume. You can snapshot it directly without connecting to the database.
# Stop the database for a consistent snapshotdocker compose stop db# Archive the volume contentsdocker run --rm \ -v breadbox_postgres_data:/data \ -v $(pwd):/backup \ alpine tar czf /backup/postgres_data_$(date +%Y%m%d).tar.gz -C /data .# Restart the databasedocker compose start db
docker compose stop db# Clear existing data and extract the archivedocker run --rm \ -v breadbox_postgres_data:/data \ -v $(pwd):/backup \ alpine sh -c "rm -rf /data/* && tar xzf /backup/postgres_data_YYYYMMDD.tar.gz -C /data"docker compose start db
Your ENCRYPTION_KEY is an environment variable (see the environment variables reference for generation and precedence rules). It’s not in the database, so database backups do not include it. Store it separately:
In a password manager (1Password, Bitwarden, etc.)
In a secrets vault (HashiCorp Vault, AWS Secrets Manager, etc.)
In encrypted offline storage
Do not commit it to version control. If you lose the key and need to recover, your transaction history remains intact but every bank connection must be re-linked by hand.
Key rotation is a manual process. To change your encryption key, you must decrypt all stored credentials with the old key, re-encrypt them with the new key, and update ENCRYPTION_KEY before restarting. Breadbox does not automate this. Plan rotations carefully.
As an alternative or supplement to database backups, you can export your transaction history through the REST API. This is useful for archiving data in a format that is independent of the database schema:
Use the cursor-based pagination in the API response to page through all records. Exported JSON does not include bank credentials, so it is safe to store without the encryption key.