Backup and restore
The runtime can export all of its persistent data to a portable file and load it back later, using the backup and restore subcommands. This is useful for disaster recovery, cloning an environment, and migrating between data stores/providers.
A backup contains everything the provider persists:
- Actor state
- Alarms, including scheduled jobs
- Dead-lettered jobs
Ephemeral data (e.g. host registrations and alarm leases) is intentionally left out, since it’s recreated automatically once hosts reconnect.
The format is provider-neutral, so a backup taken from one provider can be restored into a different one (for example, from SQLite into PostgreSQL)
Both subcommands discover their configuration the same way the runtime does
(the FRANCIS_CONFIG environment variable, then the well-known paths) and connect to the data store named by provider.connectionString.
Creating a backup#
francis backup -f backup.francisThe -f flag is required and names the destination file. Use -f - to write the backup to stdout instead, which lets you pipe and/or compress it:
# Compress on the fly
francis backup -f - | gzip > backup.francis.gzTaking a backup is safe against a live (running) cluster.
When running from a container, invoke the subcommand inside it with the config and data store mounted, and redirect stdout on the host:
docker run --rm \
-v "$(pwd)/config.yaml:/etc/francis/config.yaml:ro" \
-v francis-data:/data \
ghcr.io/italypaleale/francis:1 \
backup -f - \
> backup.francisRestoring a backup#
Restore wipes all existing persistent data and then loads the snapshot:
francis restore -f backup.francisUse -f - to read from stdin:
gunzip -c backup.francis.gz | francis restore -f -Restore also works against an empty database.
Note: Restore refuses to run while hosts are connected
Restoring underneath live hosts would corrupt running actors, sorestorechecks the target database for connected hosts first. If any host has reported a health check within thehealthCheckDeadline, the command exits with a non-zero status and changes nothing. Stop every host and any runtime replica sharing the database before restoring.
From a container, pass -i so stdin is forwarded:
cat backup.francis \
| docker run --rm -i \
-v "$(pwd)/config.yaml:/etc/francis/config.yaml:ro" \
-v francis-data:/data \
ghcr.io/italypaleale/francis:1 \
restore -f -Migrating between data stores#
Because the backup format is provider-neutral, you can move data between backends by backing up with one connection string and restoring with another. For example, to migrate from SQLite to PostgreSQL:
# Export from the current (SQLite) store
FRANCIS_CONFIG=./sqlite-config.yaml francis backup -f - \
| FRANCIS_CONFIG=./postgres-config.yaml francis restore -f -Note: The in-memory provider can’t be backed up from the CLI.