Backups
Configure backup destinations, create schedules, and manage retention policies with GFS tiering.
oCore provides a comprehensive backup system with support for multiple storage destinations, scheduled backups with Grandfather-Father-Son (GFS) retention, WAL archiving for point-in-time recovery, and one-click restore. This page covers configuring backup destinations, creating manual and scheduled backups, restoring from backups, and managing retention policies.
Backup Management
View and manage backups for your environment.
Backup Destinations
Before creating backups, configure at least one storage destination where backup files will be stored.
Supported Destination Types
| Type | Description |
|---|---|
s3 | Amazon S3 bucket |
s3_compatible | S3-compatible storage (MinIO, Wasabi, Backblaze B2, etc.) |
sftp | SFTP server |
local | Local filesystem on the server |
onedrive | Microsoft OneDrive |
gdrive | Google Drive |
Creating a Destination
Navigate to Settings > Backup Destinations in your organization settings.
Click Add Destination and select the type.
Provide the required configuration for your chosen type. For example, S3 requires:
- Bucket name
- Region
- Access key ID
- Secret access key
- Optional: custom endpoint, path prefix
Click Test Connection to verify the destination is reachable and writable.
Click Save to create the destination.
curl -X POST https://ocore.example.com/api/backup-destinations \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Production S3 Bucket",
"destinationType": "s3",
"config": {
"bucket": "ocore-backups",
"region": "eu-west-1",
"accessKeyId": "AKIA...",
"secretAccessKey": "..."
}
}'ocore backup-destination create \
--name "Production S3 Bucket" \
--type s3 \
--bucket ocore-backups \
--region eu-west-1Encrypted Storage
Destination credentials (access keys, passwords) are encrypted at rest using AES-256 before being stored in the database. The plaintext credentials are never persisted.
Testing a Destination
Verify connectivity and write permissions:
curl -X POST https://ocore.example.com/api/backup-destinations/{destId}/test \
-H "Authorization: Bearer $TOKEN"Listing Destinations
curl https://ocore.example.com/api/backup-destinations \
-H "Authorization: Bearer $TOKEN"The response includes the isVerified flag and lastTestedAt timestamp for each destination.
Creating Manual Backups
Create an on-demand backup for any environment:
curl -X POST https://ocore.example.com/api/environments/{envId}/backups \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"backupType": "full"}'ocore backup create --environment ENV_UUID --type fullBackup Types
| Type | Includes | Use Case |
|---|---|---|
db | Database dump only | Quick backups, database-only restores |
full | Database + filestore + config | Complete instance state, disaster recovery |
Each backup records:
- Status --
pending,in_progress,completed,failed - Size -- Total backup size in bytes
- Checksums -- SHA-256 checksums for database, filestore, and config components
- GFS Tiers -- Which retention tiers this backup belongs to
- Remote Paths -- Where the backup is stored per destination
- Timestamps -- Start time, completion time, creation time
Setting Up Scheduled Backups
Configure automatic backups on a recurring schedule with GFS (Grandfather-Father-Son) retention.
Creating a Schedule
curl -X PUT https://ocore.example.com/api/environments/{envId}/backup-schedule \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"enabled": true,
"dbFrequency": "6h",
"fullFrequency": "daily",
"retainHourly": 24,
"retainDaily": 7,
"retainWeekly": 4,
"retainMonthly": 12,
"walEnabled": true,
"walRetentionDays": 7,
"destinationIds": ["DEST_UUID_1", "DEST_UUID_2"]
}'ocore backup schedule set \
--environment ENV_UUID \
--db-frequency 6h \
--full-frequency daily \
--retain-hourly 24 \
--retain-daily 7 \
--destinations DEST_UUID_1,DEST_UUID_2Schedule Options
| Field | Values | Description |
|---|---|---|
dbFrequency | hourly, 6h, 12h, daily | How often to take database-only backups |
fullFrequency | daily, weekly | How often to take full backups |
retainHourly | Integer (>= 0) | Number of hourly backups to keep |
retainDaily | Integer (>= 0) | Number of daily backups to keep |
retainWeekly | Integer (>= 0) | Number of weekly backups to keep |
retainMonthly | Integer (>= 0) | Number of monthly backups to keep |
walEnabled | Boolean | Enable WAL archiving for point-in-time recovery |
walRetentionDays | Integer (>= 1) | Days to retain WAL segments |
destinationIds | Array of UUIDs | Where to store backups |
Viewing Schedule
curl https://ocore.example.com/api/environments/{envId}/backup-schedule \
-H "Authorization: Bearer $TOKEN"The response includes nextDbBackupAt and nextFullBackupAt timestamps showing when the next backups will run.
Restoring from Backups
Restore a backup to the same environment, a new environment, or a different existing environment. See the Databases page for detailed restore instructions including point-in-time recovery.
Restore Overwrites Data
Restoring to the same or other target type overwrites the existing database and filestore. The restore process creates a pre-restore snapshot automatically for safety.
Cross-Environment Restore
oCore supports restoring backups across environments within the same project. This is useful for:
- Refreshing staging from a production backup
- Creating test environments from known-good data
- Disaster recovery to a different environment on a different server
The restore dialog lets you choose from three target types:
| Target | Description | Use Case |
|---|---|---|
same | Restore to the same environment | Rollback to a known state |
other | Restore to a different existing environment (select from dropdown) | Refresh staging from production |
new | Create a new environment with the backup data (provide a name) | Create ad-hoc test environments |
When restoring to a different environment:
- The dialog lists all environments in the project
- You can restore both backups and snapshots
- The source environment type is shown for reference
- A pre-restore snapshot is created on the target for safety
Post-Restore Neutralization
When restoring a production backup to a staging or development environment, consider running neutralization afterward to disable outgoing emails, scheduled actions, and payment processors.
PITR Slider
When WAL archiving is enabled, the restore dialog includes an interactive point-in-time recovery (PITR) slider. The slider:
- Fetches WAL coverage data from the backend showing available time ranges
- Displays covered ranges visually on a timeline track
- Snaps the selected timestamp to the nearest covered range if you click outside a covered window
- Shows the selected recovery point as an ISO 8601 timestamp
- Validates that the chosen timestamp falls within an available WAL segment
To use the PITR slider, select a backup as the base and drag the slider to choose a recovery point between the backup creation time and the end of WAL coverage.
# Restore with PITR via API
curl -X POST https://ocore.example.com/api/backups/{backupId}/restore \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"targetType": "same",
"pitrTimestamp": "2026-03-15T14:30:00Z"
}'Backup Retention Policies
GFS Tiering
oCore implements Grandfather-Father-Son retention to balance storage costs with recovery options:
| Tier | Description | Typical Retention |
|---|---|---|
| Hourly | Most recent backups for quick recovery | 24 backups |
| Daily | One backup per day for short-term history | 7 backups |
| Weekly | One backup per week for medium-term history | 4 backups |
| Monthly | One backup per month for long-term archival | 12 backups |
When a scheduled backup runs, oCore automatically assigns it to the appropriate GFS tiers based on timing. Backups outside retention windows are automatically deleted from all destinations.
Recommended Retention Policies
| Environment | DB Frequency | Full Frequency | Hourly | Daily | Weekly | Monthly |
|---|---|---|---|---|---|---|
| Production | 6h | daily | 24 | 7 | 4 | 12 |
| Staging | daily | weekly | 0 | 7 | 2 | 0 |
| Development | daily | weekly | 0 | 3 | 0 | 0 |
Backup Alerts
oCore generates alerts for backup-related events:
- Backup failed -- A scheduled or manual backup did not complete
- Destination unreachable -- A backup destination failed connectivity test
- Retention warning -- Backup retention is running low
View alerts:
curl https://ocore.example.com/api/backup-alerts \
-H "Authorization: Bearer $TOKEN"Each alert includes:
alertType-- The type of alertseverity--info,warning,error,criticalmessage-- Human-readable descriptionisRead-- Whether the alert has been acknowledged
Multi-Destination Backups
You can configure a schedule to write backups to multiple destinations simultaneously. This provides redundancy -- if one destination fails, backups are still available from others.
{
"destinationIds": ["s3-primary-uuid", "sftp-secondary-uuid"]
}The backup records remotePaths showing the storage location per destination.
Required Permissions
Backup management requires manage:environments permission. Viewing backups requires view:environments. Backup destination management requires manage:org_settings.
Troubleshooting
Backup fails with "destination unreachable"
- Test the backup destination to verify connectivity
- Check that the destination credentials are still valid (keys not rotated)
- For S3 destinations, verify the bucket exists and the IAM policy allows writes
- For SFTP destinations, verify the SSH key or password is correct
Scheduled backups not running
- Check that the schedule is
enabled: true - Verify at least one destination is configured
- Check the backup alert list for error details
- Verify the oCore job queue is running (River workers)
Backup size growing unexpectedly
- Check the filestore for large uploads or attachments
- Review database growth with
pg_database_size() - Consider more frequent full backups with shorter retention to manage storage
Restore hangs or takes very long
- Large databases take longer to restore -- check the restore progress endpoint
- Verify sufficient disk space on the target server
- For cross-server restores, network bandwidth is the bottleneck
- Check the operation logs for detailed step timing
WAL archiving filling up disk
- Reduce
walRetentionDaysto clean up older WAL segments - Ensure WAL segments are being uploaded to the backup destination
- Check that the backup destination has sufficient storage