> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/pocketbase/pocketbase/llms.txt
> Use this file to discover all available pages before exploring further.

# Backups and restore

> Learn how to create, manage, and restore PocketBase backups

PocketBase provides built-in backup and restore functionality to protect your data. Backups include the entire `pb_data` directory (excluding the backups folder itself) packaged as a zip archive.

## Understanding backups

Backups in PocketBase:

* Create a complete snapshot of your `pb_data` directory
* Are executed within a database transaction (writes are temporarily blocked)
* Include the database and all local storage files
* Exclude the `backups/`, `.pb_temp/`, and autocert cache directories
* Can be stored locally or on S3-compatible storage

<Warning>
  If you use S3 storage for collection files, those files are **not** included in PocketBase backups. You must back up S3 separately using your cloud provider's backup tools.
</Warning>

## Storage requirements

To safely perform backups, ensure you have:

* **Free disk space**: At least 2x the size of your `pb_data` directory
* **Sufficient I/O**: Backups run in a transaction and temporarily block writes

<Info>
  Backup creation uses SQLite's `PRAGMA wal_checkpoint(TRUNCATE)` to ensure database consistency.
</Info>

## Creating backups manually

### Via admin UI

1. Navigate to **Settings** → **Backups** in the admin dashboard
2. Click **Create backup**
3. Enter a backup name (optional, auto-generated if empty)
4. Click **Create**

The backup will be created with a name like `pb_backup_myapp_20240303120000.zip`.

### Via API

Create a backup programmatically using the API:

```javascript theme={null}
// Authenticate as superuser first
const authData = await pb.admins.authWithPassword(email, password);

// Create backup
await fetch('http://your-domain.com/api/backups', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${authData.token}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    name: 'manual_backup_20240303.zip'
  })
});
```

<Note>
  Backup names must match the pattern: `^[a-z0-9_-]+\.zip$`
</Note>

### Programmatically in Go

If you're extending PocketBase with Go, you can create backups programmatically:

```go theme={null}
import (
    "context"
    "github.com/pocketbase/pocketbase/core"
)

// Create backup with auto-generated name
err := app.CreateBackup(context.Background(), "")
if err != nil {
    log.Fatal(err)
}

// Create backup with custom name
err = app.CreateBackup(context.Background(), "my_backup_20240303.zip")
if err != nil {
    log.Fatal(err)
}
```

The `CreateBackup` method from `core/base_backup.go:44`:

```go theme={null}
func (app *BaseApp) CreateBackup(ctx context.Context, name string) error
```

Key behaviors:

* Blocks if another backup/restore is in progress (checked via `StoreKeyActiveBackup`)
* Triggers `OnBackupCreate` hooks for customization
* Auto-generates name if not provided
* Runs in a transaction to ensure data consistency
* Automatically excludes backup directory and temp files

## Automated backups

Configure automatic backups using a cron expression:

### Via admin UI

1. Go to **Settings** → **Backups**
2. Enter a cron expression (e.g., `0 2 * * *` for daily at 2 AM)
3. Set **Max backups to keep** (e.g., `7` for one week)
4. Click **Save**

### Cron expression format

PocketBase uses standard cron syntax:

```
┌───────────── minute (0 - 59)
│ ┌───────────── hour (0 - 23)
│ │ ┌───────────── day of month (1 - 31)
│ │ │ ┌───────────── month (1 - 12)
│ │ │ │ ┌───────────── day of week (0 - 6) (Sunday to Saturday)
│ │ │ │ │
* * * * *
```

Common examples:

| Expression    | Description                   |
| ------------- | ----------------------------- |
| `0 2 * * *`   | Daily at 2:00 AM              |
| `0 */6 * * *` | Every 6 hours                 |
| `0 0 * * 0`   | Weekly on Sunday at midnight  |
| `0 3 1 * *`   | Monthly on the 1st at 3:00 AM |

### Automatic cleanup

When `cronMaxKeep` is set, PocketBase automatically removes old backups:

```go theme={null}
// From core/base_backup.go:321-366
maxKeep := app.Settings().Backups.CronMaxKeep

if maxKeep == 0 {
    return // no explicit limit
}

// List auto-generated backups
files, err := fsys.List("@auto_pb_backup_")

// Sort by modification time (descending)
sort.Slice(files, func(i, j int) bool {
    return files[i].ModTime.After(files[j].ModTime)
})

// Keep only the most recent n backups
toRemove := files[maxKeep:]
```

<Info>
  Auto-generated backups are prefixed with `@auto_pb_backup_` to distinguish them from manual backups.
</Info>

## S3 storage for backups

Store backups on S3-compatible storage for off-site redundancy:

### Configuration

```json theme={null}
{
  "backups": {
    "cron": "0 2 * * *",
    "cronMaxKeep": 7,
    "s3": {
      "enabled": true,
      "bucket": "my-app-backups",
      "region": "us-east-1",
      "endpoint": "s3.amazonaws.com",
      "accessKey": "YOUR_ACCESS_KEY",
      "secret": "YOUR_SECRET_KEY",
      "forcePathStyle": false
    }
  }
}
```

### S3-compatible providers

PocketBase works with any S3-compatible storage:

* **AWS S3**: Standard S3 service
* **Backblaze B2**: Set `endpoint` to `s3.us-west-000.backblazeb2.com`
* **DigitalOcean Spaces**: Set `endpoint` to `nyc3.digitaloceanspaces.com`
* **MinIO**: Self-hosted S3-compatible storage
* **Wasabi**: Cost-effective cloud storage

<Note>
  Some providers require `forcePathStyle: true` for proper URL formatting.
</Note>

## Listing backups

### Via admin UI

View all backups in **Settings** → **Backups**.

### Via API

```javascript theme={null}
const backups = await fetch('http://your-domain.com/api/backups', {
  headers: {
    'Authorization': `Bearer ${authData.token}`
  }
}).then(r => r.json());

console.log(backups);
// [
//   {
//     "key": "pb_backup_myapp_20240303120000.zip",
//     "size": 1048576,
//     "modified": "2024-03-03 12:00:00.000Z"
//   }
// ]
```

## Downloading backups

### Via admin UI

1. Go to **Settings** → **Backups**
2. Click the download icon next to the backup
3. Authorize with your superuser credentials

### Via API

Backup downloads require a file token:

```javascript theme={null}
// Generate a file token
const token = authData.token; // Your superuser auth token

// Download backup
const downloadUrl = `http://your-domain.com/api/backups/${backupKey}?token=${token}`;
window.location.href = downloadUrl;
```

## Restoring backups

<Warning>
  Restore functionality is **experimental** and only works on Unix-based systems (Linux and macOS). Windows is not supported.
</Warning>

### Prerequisites

* Free disk space: At least 2x the backup size
* Unix-based operating system
* Superuser access

### Restore process

The restore process (from `core/base_backup.go:149-295`):

<Steps>
  <Step title="Download and extract">
    PocketBase downloads the backup (from S3 if configured) and extracts it to a temporary directory inside `pb_data/.pb_temp/`.
  </Step>

  <Step title="Validate backup">
    Verifies that `data.db` exists in the extracted backup.
  </Step>

  <Step title="Move current data">
    Moves the current `pb_data` content (excluding backups and temp) to a temporary location: `pb_data/.pb_temp/old_pb_data_*`.
  </Step>

  <Step title="Move restored data">
    Moves the extracted backup content to the `pb_data` directory.
  </Step>

  <Step title="Restart application">
    Restarts the PocketBase process. On successful startup, old data is automatically deleted.
  </Step>
</Steps>

### Via admin UI

1. Go to **Settings** → **Backups**
2. Click the restore icon next to the backup
3. Confirm the restore operation
4. PocketBase will restart automatically

### Via API

```javascript theme={null}
await fetch(`http://your-domain.com/api/backups/${backupKey}/restore`, {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${authData.token}`
  }
});

// The server will restart after ~1 second
```

### Programmatically in Go

```go theme={null}
import (
    "context"
    "time"
)

// Restore backup
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute)
defer cancel()

err := app.RestoreBackup(ctx, "backup_name.zip")
if err != nil {
    log.Fatal(err)
}
// App will restart automatically
```

### Error recovery

If restore fails, PocketBase attempts to revert changes:

```go theme={null}
// From core/base_backup.go:268-282
if err := e.App.Restart(); err != nil {
    if revertErr := revertDataDirChanges(); revertErr != nil {
        panic(revertErr) // Cannot recover
    }
    return fmt.Errorf("failed to restart the app process: %w", err)
}
```

<Warning>
  If the revert process fails, the application will panic. Always ensure you have external backups before attempting restoration.
</Warning>

## Deleting backups

### Via admin UI

1. Go to **Settings** → **Backups**
2. Click the delete icon
3. Confirm deletion

### Via API

```javascript theme={null}
await fetch(`http://your-domain.com/api/backups/${backupKey}`, {
  method: 'DELETE',
  headers: {
    'Authorization': `Bearer ${authData.token}`
  }
});
```

<Note>
  You cannot delete a backup that's currently being created or restored.
</Note>

## Backup hooks

Customize backup behavior using hooks in your Go application:

```go theme={null}
app.OnBackupCreate().BindFunc(func(e *core.BackupEvent) error {
    // Before backup creation
    log.Println("Creating backup:", e.Name)
    
    // Exclude additional directories
    e.Exclude = append(e.Exclude, "custom_temp")
    
    // Continue with backup
    return e.Next()
})

app.OnBackupRestore().BindFunc(func(e *core.BackupEvent) error {
    // Before backup restoration
    log.Println("Restoring backup:", e.Name)
    
    // Add custom validation
    if e.Name == "protected_backup.zip" {
        return errors.New("this backup is protected")
    }
    
    return e.Next()
})
```

## Best practices

<Accordion title="Test restore procedures regularly">
  Schedule quarterly restore tests to verify backup integrity:

  1. Download a recent backup
  2. Restore to a test environment
  3. Verify data completeness
  4. Test critical application functions
  5. Document any issues
</Accordion>

<Accordion title="Implement 3-2-1 backup strategy">
  Maintain multiple backup copies:

  * **3** total copies of your data
  * **2** different storage types (e.g., local + S3)
  * **1** off-site copy
</Accordion>

<Accordion title="Monitor backup size and duration">
  Track backup metrics:

  ```javascript theme={null}
  const backups = await pb.collection('_backups').getList();
  const latest = backups.items[0];

  console.log(`Latest backup: ${latest.size / 1024 / 1024}MB`);
  ```

  Alert on anomalies like sudden size increases or long backup times.
</Accordion>

<Accordion title="Secure backup access">
  * Store S3 credentials securely (use environment variables)
  * Enable S3 bucket versioning for additional protection
  * Restrict backup API access to superusers only
  * Encrypt backups at rest and in transit
</Accordion>

<Accordion title="Plan for disaster recovery">
  Document your recovery procedures:

  1. Where backups are stored
  2. How to access backups during an outage
  3. Step-by-step restoration process
  4. Contact information for team members
  5. Estimated recovery time objective (RTO)
</Accordion>

## Troubleshooting

### Backup creation fails

**Error**: "Try again later - another backup/restore process has already been started"

**Solution**: Wait for the current backup/restore to complete, or restart PocketBase if the process is stuck.

### Insufficient disk space

**Error**: "Failed to create backup" with I/O errors

**Solution**: Free up disk space. You need at least 2x your `pb_data` directory size.

### S3 connection errors

**Error**: "Failed to load backups filesystem"

**Solutions**:

* Verify S3 credentials are correct
* Check bucket name and region
* Ensure `forcePathStyle` matches your provider's requirements
* Verify network connectivity to S3 endpoint

### Restore fails on Windows

**Error**: "Restore is not supported on Windows"

**Solution**: Restore manually:

1. Stop PocketBase
2. Extract backup zip
3. Replace `pb_data` contents
4. Start PocketBase

## Next steps

<CardGroup cols={2}>
  <Card title="Going to production" icon="rocket" href="/deployment/going-to-production">
    Learn production deployment best practices
  </Card>

  <Card title="Migrations" icon="code" href="/deployment/migrations">
    Manage database schema changes
  </Card>
</CardGroup>
