Backup and Restore
Scheduler0 provides built-in database backup and restore capabilities using SQLite's Online Backup API. This allows you to safely backup and restore your database even while the cluster is running.
Overview
The backup/restore feature provides:
- Automatic timestamped backups - Create backups with automatic naming
- Custom path backups - Backup to a specific file path
- Database restore - Restore from any backup file
- Real-time progress tracking - Monitor backup/restore operations
- Leader-only operations - Ensures consistency by restricting to leader node
- Safe concurrent access - Uses SQLite Online Backup API for safe operation
API Endpoints
Start Automatic Backup
Initiates a backup with an automatic timestamped filename.
POST /api/v1/cluster/backup
Response (202 Accepted):
{
"success": true,
"data": {
"status": "backup initiated"
}
}
Backup to Specific File
Initiates a backup to a specific destination path.
POST /api/v1/cluster/backup-to-file
Content-Type: application/json
{
"destPath": "/path/to/backup-20260113-143000.db"
}
Response (202 Accepted):
{
"success": true,
"data": {
"status": "backup to file initiated"
}
}
Restore from Backup
Initiates a restore from a backup file.
POST /api/v1/cluster/restore
Content-Type: application/json
{
"backupPath": "/path/to/backup-20260113-143000.db"
}
Response (202 Accepted):
{
"success": true,
"data": {
"status": "restore initiated"
}
}
Get Progress
Retrieves the current backup/restore progress.
GET /api/v1/cluster/backup-restore-progress
Response (200 OK):
{
"success": true,
"data": {
"operationType": "backup",
"status": "in-progress",
"progress": 45,
"message": "Backing up: 4500/10000 rows (45.0%)",
"startTime": "2026-01-13T14:30:00Z",
"endTime": "0001-01-01T00:00:00Z",
"backupPath": ""
}
}
On completion:
{
"success": true,
"data": {
"operationType": "backup",
"status": "completed",
"progress": 100,
"message": "Backup completed: /path/to/sqlite_data/backups/db-20260113-143015.db",
"startTime": "2026-01-13T14:30:00Z",
"endTime": "2026-01-13T14:30:15Z",
"backupPath": "/path/to/sqlite_data/backups/db-20260113-143015.db"
}
}
Progress Status Values
idle- No operation in progressin-progress- Operation currently runningcompleted- Operation finished successfullyfailed- Operation failed (check message for error)
Operation Types
backup- Automatic timestamped backupbackup-to-file- Backup to specific pathrestore- Database restore
Client SDKs
Go Client
import scheduler0 "github.com/scheduler0/scheduler0-go-client"
// Create client with basic auth (for cluster operations)
client, _ := scheduler0.NewBasicAuthClient(
"http://localhost:7070",
"v1",
"username",
"password",
)
// Start automatic backup
result, err := client.BackupDatabase()
if err != nil {
log.Fatal(err)
}
fmt.Printf("Status: %s\n", result.Data["status"])
// Poll for progress
for {
progress, err := client.GetBackupRestoreProgress()
if err != nil {
log.Fatal(err)
}
fmt.Printf("%s: %d%% - %s\n",
progress.Data.OperationType,
progress.Data.Progress,
progress.Data.Message)
if progress.Data.Status == "completed" {
fmt.Printf("Backup path: %s\n", progress.Data.BackupPath)
break
}
if progress.Data.Status == "failed" {
log.Fatal("Backup failed")
}
time.Sleep(2 * time.Second)
}
// Backup to specific file
result, err = client.BackupDatabaseToFile("/path/to/backup.db")
// Restore from backup
result, err = client.RestoreDatabase("/path/to/backup.db")
Node.js Client
import { Client } from 'scheduler0-node-client';
// Create client with basic auth
const client = Client.newBasicAuthClient(
'http://localhost:7070',
'v1',
'username',
'password'
);
// Start automatic backup
const result = await client.backupDatabase();
console.log(`Status: ${result.data.status}`);
// Poll for progress
while (true) {
const progress = await client.getBackupRestoreProgress();
console.log(`${progress.data.operationType}: ${progress.data.progress}% - ${progress.data.message}`);
if (progress.data.status === 'completed') {
console.log(`Backup path: ${progress.data.backupPath}`);
break;
}
if (progress.data.status === 'failed') {
throw new Error('Backup failed');
}
await new Promise(resolve => setTimeout(resolve, 2000));
}
// Backup to specific file
await client.backupDatabaseToFile('/path/to/backup.db');
// Restore from backup
await client.restoreDatabase('/path/to/backup.db');
Python Client
from scheduler0 import Client, backup
import time
# Create client with basic auth
client = Client.NewBasicAuthClient(
"http://localhost:7070",
"v1",
"username",
"password"
)
# Start automatic backup
result = backup.backup_database(client)
print(f"Status: {result['data']['status']}")
# Poll for progress
while True:
progress = backup.get_backup_restore_progress(client)
data = progress['data']
print(f"{data['operationType']}: {data['progress']}% - {data['message']}")
if data['status'] == 'completed':
print(f"Backup path: {data['backupPath']}")
break
if data['status'] == 'failed':
raise Exception('Backup failed')
time.sleep(2)
# Backup to specific file
backup.backup_database_to_file(client, '/path/to/backup.db')
# Restore from backup
backup.restore_database(client, '/path/to/backup.db')
CLI
Start Automatic Backup
scheduler0 backup start
Backup to Specific File
scheduler0 backup to-file /path/to/backup.db
Restore from Backup
scheduler0 backup restore /path/to/backup.db
Check Progress
scheduler0 backup progress
Watch Progress in Real-Time
scheduler0 backup watch
This will continuously poll and display progress until the operation completes:
Watching backup/restore progress (Ctrl+C to stop)...
[14:30:05] backup: 0% - Starting backup...
[14:30:07] backup: 25% - Backing up: 2500/10000 rows (25.0%)
[14:30:09] backup: 50% - Backing up: 5000/10000 rows (50.0%)
[14:30:11] backup: 75% - Backing up: 7500/10000 rows (75.0%)
[14:30:13] backup: 100% - Backup completed: /path/to/sqlite_data/backups/db-20260113-143015.db
Operation finished!
Backup path: /path/to/sqlite_data/backups/db-20260113-143015.db
Backup Location
By default, automatic backups are stored in:
<database-directory>/backups/<database-name>-YYYYMMDD-HHMMSS.db
For example:
/path/to/sqlite_data/backups/db-20260113-143015.db
Best Practices
- Regular Backups - Schedule regular backups using cron or similar
- Off-site Storage - Copy backups to off-site storage for disaster recovery
- Test Restores - Periodically test restore operations to ensure backups are valid
- Monitor Progress - Use the progress endpoint to monitor long-running operations
- Leader Node - Backup/restore operations are automatically restricted to the leader node
- Pre-restore Backup - The system automatically creates a pre-restore backup for safety
Safety Features
- Pre-restore Backup - Before restoring, the current database is automatically backed up to
.pre-restore-backup - Atomic Operations - Uses SQLite's Online Backup API for safe, atomic operations
- Connection Locking - Prevents concurrent database modifications during backup/restore
- Progress Tracking - Real-time progress updates for monitoring
- Error Recovery - Failed operations are logged and partial backups are cleaned up
Troubleshooting
Backup Fails to Start
- Ensure you're authenticated with proper credentials
- Verify the node is the cluster leader
- Check disk space availability
Restore Fails
- Verify the backup file exists and is readable
- Ensure the backup file is a valid SQLite database
- Check that no other operations are in progress
Progress Shows "idle"
- No backup/restore operation has been initiated
- Previous operation has completed
- Start a new operation to see progress
Notes
- Only one backup/restore operation can run at a time
- Operations are restricted to the leader node for consistency
- The database remains accessible during backup operations
- Restore operations temporarily close and reopen the database connection