Cloud SQL for PostgreSQL: scheduled export to Cloud Storage

Verified against the provider's documentation, not against a live account.

Cloud SQL's own backups stay inside Google's service and are lost with the project. Keep an export in Cloud Storage: a bucket in another project (or with another provider) survives the loss of the instance's project, and Verestore proves it restores.

1. Let the instance write to the bucket

Find the instance's service account and grant it roles/storage.objectCreator on the bucket. Google's documentation names roles/storage.objectAdmin or a custom role with storage.objects.create; Object Creator carries exactly that permission, enough for a single-file export (parallel exports also need list and delete):

SA=$(gcloud sql instances describe INSTANCE --format='value(serviceAccountEmailAddress)')
gcloud storage buckets add-iam-policy-binding gs://acme-backups \
  --member="serviceAccount:$SA" --role=roles/storage.objectCreator

If the export fails with a permission error, check the provider's current documentation for the role it requires.

2. Export one database

gcloud sql export sql INSTANCE \
  "gs://acme-backups/orders/orders-$(date -u +%Y-%m-%dT%H-%M).sql.gz" \
  --database=orders --offload

This writes plain SQL; the .gz suffix makes Cloud SQL compress it. --offload uses a serverless export, which avoids load on the primary (check Google's pricing for it). Verestore detects the format from the content, not the extension.

The export contains statements that reference Cloud SQL roles such as cloudsqlsuperuser. Verestore creates missing roles as NOLOGIN in the scratch server and reports them as warnings.

3. Schedule the export

Keep it simple: a Cloud Scheduler job that triggers a Cloud Run job (or a Cloud Function) which calls the Cloud SQL Admin API export, at a time before your Verestore schedule. The request body for POST https://sqladmin.googleapis.com/v1/projects/PROJECT/instances/INSTANCE/export is:

{
  "exportContext": {
    "fileType": "SQL",
    "uri": "gs://acme-backups/orders/orders-2026-11-05T02-00.sql.gz",
    "databases": ["orders"],
    "offload": true
  }
}

Generate the date in the file name in your job, so each export is a new object and Verestore picks the newest. Google publishes a guide to scheduling Cloud SQL exports with Cloud Scheduler: check it for the current setup and the roles the calling service account needs.

4. Give Verestore read access

The read side is the same as for any Cloud Storage bucket: a dedicated verestore-reader service account with roles/storage.objectViewer on the bucket and an HMAC interoperability key. Follow Google Cloud Storage, then add the target:

  • S3 endpoint: https://storage.googleapis.com
  • Region: auto (or leave it empty: it is filled from the endpoint)
  • Bucket: acme-backups
  • Prefix: orders/
  • Access key ID and secret access key: the HMAC access ID and secret