CWDBBackup resource when you want an explicit on-demand recovery point. Restores always provision a new database. CWDB doesn’t modify the source database.
This page explains how automatic backups work, how to take on-demand backups, and how to restore from a backup into a new database.
How automatic backups work
For every database, the operator runs two coordinated backup streams against CoreWeave-managed object storage:- Daily base backups of the entire database, retained for 7 days. The schedule is configurable. See Customize the backup schedule.
- Continuous write-ahead log (WAL) archiving, which streams every change to backup storage to keep base backups consistent and to support restores.
Customize the backup schedule
To run base backups on a different cadence, setspec.postgres.backupSchedule on the CWDBCluster manifest to a cron expression. By default, CWDB takes one base backup per database per day at midnight (equivalent to a 0 0 0 * * * cron expression). The following example schedules base backups every two hours, at the 15-minute mark:
0 0 6 * * * triggers a backup at 6 AM in the cluster’s region, not at 6 AM UTC. You can change backupSchedule after the database is created. The operator applies the new cadence on the next reconcile.
CWDB uses the CNPG backup schedule format, which is a six-field cron expression. The first field is seconds, not minutes. This differs from the more common five-field Unix cron format:
For the full set of supported expressions and predefined schedules, see the robfig/cron documentation, the underlying parser CNPG uses.
The following table describes the field:
Retention is fixed at 7 days regardless of cadence. More frequent base backups produce more recovery points within the same 7-day window, not a longer backup history. For most workloads, daily base backups are sufficient. Schedule more frequent base backups only when you have a recovery-point objective the default cadence doesn’t meet. Continuous WAL archiving already covers the gap between base backups for restores.
Opt out of managed backups
Managed backups are on by default for every database. To opt out, setspec.postgres.disableManagedBackups: true on the manifest. The CoreWeave Cloud Console exposes this as the Enable backups toggle in the Create database form (see Create a database).
View backup status
The CWDB operator surfaces backup history on theCWDBCluster resource and in the Cloud Console.
View backups from the Cloud Console
The Cloud Console exposes a Backups tab on each database’s details panel. The tab lists every available backup for the database, including scheduled base backups and on-demand backups. It’s also the entry point for the Take backup and Restore actions described later on this page. To open the Backups tab, follow these steps:- In the Cloud Console, open Infrastructure > Data and storage and select the Databases tab.
-
Open the Backups tab in one of two ways:
- Click the database row to open the details view, then click the Backups tab alongside Details and YAML.
- In the row’s three-dot menu, select Manage backups.
Scheduled or On-demand badge, the compressed size, and the backup ID. Entries are grouped by day and sorted from newest to oldest. To copy a backup ID, click the copy icon next to it. When you restore from a specific backup with kubectl, pass this value to spec.postgres.restore.backupID.
The search field above the list accepts free-text matches against backup IDs and supports filtering by field. To list only one backup type, enter type:scheduled or type:on-demand in the search field.
View backups with kubectl
TheCWDBCluster resource reflects the status of automatic backups:
status.backupStatus section reports the timestamp of the most recent successful base backup, current WAL archiving health, and a list of available backups under availableBackups. Each entry in availableBackups includes a composite backupID, timestamp, type (Scheduled or OnDemand), and size. These identifiers are the values you pass to spec.postgres.restore.backupID when restoring from a specific backup.
Create an on-demand backup
An on-demand backup is an explicit recovery point that you create outside the daily schedule. Use one before any operation you want a precise rollback point for: major version upgrades, schema migrations, large data imports, or one-off batch jobs. You can take an on-demand backup from the Cloud Console or by applying aCWDBBackup resource with kubectl. Both methods create the same CWDBBackup resource and count against the on-demand backup quotas.
Create from the Cloud Console
To take an on-demand backup from the Cloud Console, follow these steps:- Open the Backups tab for the database.
- At the top right of the Backups tab, click Take backup.
CWDBBackup resource with an auto-generated name and shows a Backup started notification. The backup appears at the top of the list under Today with an On-demand badge as soon as the operator picks it up, and the size column updates from — to the compressed size when the backup completes.
The Cloud Console doesn’t let you set the CWDBBackup resource name. When you need a specific resource name (for example, to reference the backup from a GitOps manifest or an automated rollback procedure), use the kubectl flow.
Create with kubectl
Create an on-demand backup with aCWDBBackup resource. Save the following manifest as cwdb_backup.yaml. Replace [BACKUP-NAME] with a name for this backup and [CLUSTER-NAME] with your database name:
cwdb_backup.yaml
CWDBBackup spec is intentionally minimal. The operator resolves the backup destination from the referenced database’s configuration. You never specify object storage details for on-demand backups.
Apply it to the same namespace as the database:
Pending, Running, and Succeeded phases. A failed backup transitions to Failed:
Succeeded, the recovery point is durable in backup storage. The status.backupID field is the identifier you pass to spec.postgres.restore.backupID when you restore from this specific backup.
On-demand backup status fields
TheCWDBBackup.status exposes the following fields:
List on-demand backups
To see all on-demand backups in a namespace and their current status, run:Example output
On-demand backup quotas
Each database has the following quotas onCWDBBackup resources:
- Maximum 50 on-demand backups per database.
- Maximum 10 TB cumulative compressed size per database, summed from
status.compressedSizeBytesacross allSucceededbackups.
CWDBBackup resources with phase=Failed if either quota would be exceeded. On-demand backups aren’t subject to the 7-day scheduled-backup retention. They persist until you delete them or until a quota cap is hit.
If your workload needs higher quotas (for example, to keep monthly recovery points for compliance), contact your CoreWeave account team.
Delete an on-demand backup
To permanently remove an on-demand backup and free its slot against the per-database quota, run:CWDBBackup resource is removed. Deletion is irreversible. If you may need the recovery point, restore from it into a new database before deleting.
Restore from a backup
A restore in CWDB creates a new database from a previously captured backup. There’s no separate restore resource. You create a newCWDBCluster and set spec.postgres.restore to point at the source database and, optionally, a specific backup. The operator bootstraps the new database from the chosen backup as part of its normal provisioning lifecycle.
Restores always create a new database. CWDB doesn’t support in-place rollback of an existing database. Common use cases include:
- Recovering after data loss or corruption.
- Cloning a production database into a sandbox for testing.
- Validating a backup before relying on it.
- Migrating to a new database after a major version upgrade or topology change.
kubectl. The Console restore flow is a quick path for a one-off recovery from an existing backup. When you need to script the restore, resize storage during the restore, or restore from user-managed object storage with spec.postgres.restoreObjectStore, use kubectl.
Restore from the Cloud Console
To restore from a specific backup using the Cloud Console, follow these steps:- Open the Backups tab for the source database.
- Locate the backup you want to restore from. Use the
type:scheduledortype:on-demandfilter to narrow the list. - On the backup row, click Restore. The Console opens a Restore from backup panel.
- Review the Backup and Configuration summaries (described in the following section) and edit New database name if you want a name other than the pre-filled default.
- Click Restore to new database.
- Backup identifies the source database, the timestamp the backup was taken, its type (
ScheduledorOn-demand), its compressed size, and its backup ID. - Configuration shows the compute and storage settings the new database inherits from the source. The Console restore flow doesn’t let you change these before provisioning. If the backup is much smaller than the inherited storage size, the panel surfaces a note that you can increase storage after provisioning.
- New database name is the name of the new
CWDBCluster. The Console pre-fills[SOURCE-NAME]-restore-[YYYYMMDD]-[HHMM]. Edit it to give the restored database a different name.
CWDBCluster with spec.postgres.restore.sourceClusterName set to the source database and spec.postgres.restore.backupID set to the selected backup’s ID. The new database appears in the Databases list with a Provisioning status and transitions to Ready once the operator has bootstrapped Postgres from the backup. The source database keeps running unchanged.
After the restored database reaches Ready, you can point your application at the new database, run both side by side, or delete either one. For the cut-over steps, see Cut over to the restored database.
A restore always provisions the new database in the same namespace as the source, whether you use the Cloud Console or
kubectl. Cross-namespace restore isn’t supported in limited availability.Restore from the latest scheduled backup
The minimum required field isspec.postgres.restore.sourceClusterName. When backupID is omitted, the operator restores from the latest entry in the source’s scheduled backup history.
Save the following manifest as cwdb_restore.yaml. Replace [SOURCE-CLUSTER-NAME] with the source database name and [NEW-CLUSTER-NAME] with a name for the new database:
cwdb_restore.yaml
Restore from a specific backup
To restore from a specific backup (for example, the on-demand backup you took before a schema migration), setspec.postgres.restore.backupID to the composite identifier of that backup:
cwdb_restore.yaml
- The
status.backupIDfield on aCWDBBackupresource. - The
status.backupStatus.availableBackupslist on the sourceCWDBCluster.
Resize storage during restore
When you restore withkubectl, you can set the new database’s spec.storage.resources.requests.storage to a different value than the source. The new database is sized according to its own manifest. The source’s storage size doesn’t carry over. Pick a size that comfortably exceeds CWDBBackup.status.actualSizeBytes for the backup you’re restoring from.
Resizing during restore isn’t available in the Cloud Console restore flow. Use kubectl when you need different storage sizing on the restored database.
Restore after deleting the source database
You can restore even after the source database has been deleted. CWDB keeps backup history in a registry independent of the source database’s lifecycle. SetsourceClusterName to the deleted database’s name and the operator looks up its backup history.
The new database can reuse the deleted source’s name. The operator allocates a fresh lifecycle context, so there’s no collision with the source’s backup data.
CWDBCluster restore fields
The following fields on a newCWDBCluster control restore behavior:
spec.postgres.restore is a one-time bootstrap instruction. After the new database reaches Ready, the operator doesn’t re-process the field on subsequent reconciles.
Monitor the restore
The newCWDBCluster goes through its normal provisioning lifecycle. Track progress with:
Provisioning while the operator bootstraps from the backup, then transitions to Ready once the database is online. Wait for Ready before cutting traffic over:
Cut over to the restored database
After the restored database isReady:
- Validate the data. Run application-level checks against the new database to confirm the expected recovery point.
- Update connection strings. Point your application at the new database’s pooler Service (
[NEW-CLUSTER-NAME]-pooler-rw). The credentials Secret is named[NEW-CLUSTER-NAME]-[DBNAME]-credentials. For the defaultdbName: app, that resolves to[NEW-CLUSTER-NAME]-app-credentials. Use[NEW-CLUSTER-NAME]-[DBNAME]-credentials-roto route read-only traffic to replicas. - Cut over traffic. Deploy the updated configuration and drain connections from the old database.
- Optional: Retire the source database. The source database is untouched by the restore. Keep it until you have confidence in the restored data, then delete it explicitly.