oCoreoCore Docs

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, durable WAL archiving, and one-click logical backup restore. WAL segments are retained for durability and future recovery support, but point-in-time restore is not currently available because full backups are logical pg_dump archives rather than physical PostgreSQL base backups. 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.

Open in Dashboard

Backup Destinations

Before creating backups, configure at least one storage destination where backup files will be stored.

Supported Destination Types

TypeDescription
s3Amazon S3 bucket
s3_compatibleS3-compatible storage (MinIO, Wasabi, Backblaze B2, etc.)
sftpSFTP server
localLocal filesystem on the server
onedriveMicrosoft OneDrive
gdriveGoogle 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-1

Encrypted 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 '{"type": "full"}'
ocore backup create --environment ENV_UUID --type full

Backup Types

TypeIncludesUse Case
dbDatabase dump onlyQuick backups, database-only restores
fullDatabase + filestore + configComplete 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_2

Schedule Options

FieldValuesDescription
dbFrequencyhourly, 6h, 12h, dailyHow often to take database-only backups
fullFrequencydaily, weeklyHow often to take full backups
retainHourlyInteger (>= 0)Number of hourly backups to keep
retainDailyInteger (>= 0)Number of daily backups to keep
retainWeeklyInteger (>= 0)Number of weekly backups to keep
retainMonthlyInteger (>= 0)Number of monthly backups to keep
walEnabledBooleanEnable durable WAL archiving. This does not enable PITR restore for logical full backups.
walRetentionDaysInteger (>= 1)Days to retain archived WAL segments
destinationIdsArray of UUIDsWhere 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 or a different existing environment in the same project. Restore-to-new orchestration and point-in-time restore are not currently available. See the Databases page for additional database restore guidance.

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 supports two target types:

TargetDescriptionUse Case
sameRestore to the same environmentRollback to a known state
otherRestore to a different existing environment in the same projectRefresh staging from production

targetType: "new" is rejected until create-and-restore orchestration is implemented.

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, oCore runs neutralization before marking the target ready. If neutralization cannot be verified, the restore is reported as partial and the target remains degraded for operator review.

Point-in-Time Recovery Availability

PITR restore is currently unavailable

Current full backups contain logical pg_dump/pg_restore artifacts. They do not record the authoritative physical base-backup checkpoint/LSN, PostgreSQL system identifier, and timeline needed to bind archived WAL to a restore base. WAL archiving remains durable storage, but it must not be treated as proof that a timestamp is recoverable.

The coverage endpoint reports this state explicitly:

{
  "available": false,
  "reasonCode": "physical_base_metadata_unavailable",
  "message": "Point-in-time restore is unavailable because current full backups are logical pg_dump archives and do not include authoritative physical base-backup checkpoint metadata required to bind WAL segments.",
  "baseBackups": [],
  "walRanges": [],
  "gaps": []
}

The restore dialog does not offer an interactive PITR selection while coverage is unavailable. API restore requests that include a non-null pitrTimestamp are rejected synchronously with HTTP 409 and error code PITR_UNAVAILABLE; no restore log, reservation, operation lock, or background job is created.

Backup Retention Policies

GFS Tiering

oCore implements Grandfather-Father-Son retention to balance storage costs with recovery options:

TierDescriptionTypical Retention
HourlyMost recent backups for quick recovery24 backups
DailyOne backup per day for short-term history7 backups
WeeklyOne backup per week for medium-term history4 backups
MonthlyOne backup per month for long-term archival12 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.

EnvironmentDB FrequencyFull FrequencyHourlyDailyWeeklyMonthly
Production6hdaily247412
Stagingdailyweekly0720
Developmentdailyweekly0300

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 alert
  • severity -- info, warning, error, critical
  • message -- Human-readable description
  • isRead -- 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, bucket versioning must be Enabled (not Suspended). The IAM policy must allow bucket-versioning inspection, current-object listing, version listing, writes, exact-version reads, and exact-version deletion: s3:GetBucketVersioning, s3:ListBucket, s3:ListBucketVersions, s3:PutObject, s3:GetObject, s3:GetObjectVersion, and s3:DeleteObjectVersion. Test Connection explicitly verifies ListBucketVersions; without it, browser/orphan scans cannot enumerate historical versions safely.
  • 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 walRetentionDays to clean up older WAL segments
  • Ensure WAL segments are being uploaded to the backup destination
  • Check that the backup destination has sufficient storage
Was this page helpful?