Skip to main content
Data loss from a failed write, a schema migration gone wrong, or an unexpected crash can leave your users without a working config file. Rolling backups give you a safety net: before each write, the plugin copies the current file to a numbered backup slot. Up to three slots are maintained, and all backup files are automatically deleted when the application exits.

Enabling rolling backups

Pass backup: true to the Configurate constructor:
const config = new Configurate({
  schema: appSchema,
  fileName: "app.json",
  baseDir: BaseDirectory.AppConfig,
  provider: JsonProvider(),
  backup: true, // off by default
});
That is the only change required. The rest of the API — create, save, patch, reset — works exactly as before.

The three backup slots

Each write rotates the existing backups and copies the current file to .bak1:
FileContents
app.json.bak1The file as it was immediately before the most recent write
app.json.bak2The file as it was before the second-to-last write
app.json.bak3The file as it was before the third-to-last write
The oldest backup (.bak3) is overwritten on each new write once all three slots are full. The file itself (app.json) always reflects the current data.

Auto-deletion on app exit

All backup files (.bak1, .bak2, .bak3) are automatically deleted when the Tauri application exits cleanly. This keeps the application data directory tidy and prevents backups from accumulating across sessions.
If the application is force-killed (e.g. via Task Manager or kill -9), the cleanup hook may not run and backup files could remain on disk. This is intentional — an abnormal exit is exactly the scenario where you may want the backups to survive for recovery.

Provider support

Rolling backups work with every file-based provider:
ProviderBackups supported
JsonProvider()Yes
YmlProvider()Yes
TomlProvider()Yes
BinaryProvider()Yes
SqliteProvider()No
SQLite is not affected by the backup option. SQLite manages durability internally through WAL (Write-Ahead Logging) mode, which already provides atomic writes and crash recovery. Setting backup: true with SqliteProvider is silently ignored.

Restoring from a backup

The plugin does not yet expose a built-in restore command. To restore from a backup manually, use the Tauri filesystem API to copy the desired backup slot over the main file.
1

Locate the config directory

Use Tauri’s appConfigDir() (or the appropriate base directory) to get the path where your config file is stored.
import { appConfigDir } from "@tauri-apps/api/path";
import { copyFile, exists } from "@tauri-apps/plugin-fs";

const dir = await appConfigDir();
2

Check which backup slots exist

Verify the backup files are present before attempting a restore.
const bak1 = `${dir}/app.json.bak1`;
const bak2 = `${dir}/app.json.bak2`;
const bak3 = `${dir}/app.json.bak3`;

const hasBak1 = await exists(bak1);
const hasBak2 = await exists(bak2);
const hasBak3 = await exists(bak3);
3

Copy the backup over the main file

To restore from the most recent backup (.bak1), copy it over app.json:
if (hasBak1) {
  await copyFile(bak1, `${dir}/app.json`);
  console.log("Restored from .bak1");
}
4

Reload the config

After the filesystem copy, load the config normally to pick up the restored data:
const restored = await config.load().unlock(KEYRING);
console.log("Restored theme:", restored.data.theme);
Restoring a backup bypasses normal write validation and migration logic. After restoring, the restored file may be at an older schema version. If your Configurate instance has migrations configured, the next load() call will run the applicable migration steps automatically.

When to use rolling backups

Rolling backups are most valuable when your config contains data that is hard to reconstruct — user-specific settings accumulated over time, local workspace state, or data that is not synced to a remote source. They add minimal overhead (a single file copy per write) and require no changes to your read or write code. For configs that are derived from remote state (fetched from a server on every launch), backups provide little benefit and can be left disabled.

Build docs developers (and LLMs) love