Skip to content

Data and backups

Your data lives in Backed up when you
A volume Annotate the Pod
PostgreSQL Declare the database and its backup schedule
An external bucket Nothing to do: it is outside the cluster

Back up a volume

deploy/base/deployment.yaml
spec:
  template:
    metadata:
      annotations:
        backup.velero.io/backup-volumes: data # (1)!
    spec:
      containers:
        - name: app
          volumeMounts:
            - name: data
              mountPath: /data
      volumes:
        - name: data
          persistentVolumeClaim:
            claimName: app-data
  1. The name of the volume in the Pod, not of the claim. Volumes without it are not backed up.

Declare a database

deploy/staging/database.yaml
apiVersion: stackgres.io/v1
kind: SGCluster
metadata:
  name: postgres
spec:
  instances: 1
  postgres:
    version: "16"
  pods:
    persistentVolume:
      size: 10Gi
  configurations:
    backups:
      - sgObjectStorage: spaces # (1)!
        cronSchedule: "30 6 * * *" # (2)!
        retention: 7
  1. The bucket, declared in objectstorage.yaml with its credentials in secrets/.
  2. In UTC.

PostgreSQL high availability

StackGres can run one primary and multiple streaming replicas. Patroni manages automatic failover; the application keeps using the same primary service name.

For an existing database manifest, configure the native StackGres fields:

deploy/production/database.yaml
spec:
  instances: 3
  profile: production
  replication:
    mode: async

This means three PostgreSQL instances total: one primary and two replicas, each with its own persistent volume. With the production profile they run on different Kubernetes nodes. Three instances require at least three schedulable nodes with enough CPU, memory and storage.

Endpoint, for a cluster named postgres Purpose
postgres:5432 Current primary: reads and writes
postgres-replicas:5432 Read-only replicas; reads can lag behind the primary

Applications must reconnect after failover. Existing connections can break, and uncommitted transactions may need retrying. HA is not zero downtime and does not replace backups.

Compose converter

The Compose converter exposes the same settings under x-stackgres. Add this block to the PostgreSQL service, alongside its existing database, secret and volume declarations:

docker/compose.production.yaml
services:
  postgres:
    x-stackgres:
      instances: 3
      profile: production
      replication:
        mode: async

The converter generates SGCluster.spec.instances, profile and replication. Defaults are one instance, the production profile and asynchronous replication. Existing hand-written manifests still use the native fields above.

Do not use deploy.replicas to request database HA. Docker would start independent PostgreSQL containers without configuring replication, potentially sharing the same data directory. The converter ignores deploy.replicas on x-stackgres services and emits a warning; only x-stackgres.instances sets the generated database instance count. This does not change Docker behavior: Docker ignores x-stackgres and still applies deploy.replicas.

Replication and profiles

Mode Trade-off
async (default) Writes do not wait for replicas. Failover can lose recently committed transactions.
sync Waits for synchronous replicas when available; can fall back to standalone writes when none are available.
strict-sync Keeps waiting for a synchronous replica; writes can block when none are available.
sync-all / strict-sync-all Corresponding synchronous behavior across all replicas.

For sync and strict-sync, optional syncInstances specifies the number of synchronous replicas (default 1), which must be smaller than instances. Synchronous modes require at least two instances. These modes trade write availability and latency for stronger durability; they are not a blanket guarantee of zero data loss.

Profile Placement and resources
production (default) Separates database Pods across nodes and applies resource requirements.
testing Allows sharing a node while applying resource requirements. Useful for a local failover rehearsal.
development Allows sharing a node and disables several resource requirements.

Three instances on a single Kind node can exercise failover between PostgreSQL processes, but cannot survive losing that node. Use profile: testing for that rehearsal.

See the official SGCluster reference and replication documentation.

Restore a database to a moment

deploy/staging/database.yaml
apiVersion: stackgres.io/v1
kind: SGCluster
metadata:
  name: postgres-restored # (1)!
spec:
  initialData:
    restore:
      fromBackup:
        name: <backup>
        pointInTimeRecovery:
          restoreToTimestamp: "2026-09-27T14:32:00Z" # (2)!
  1. A restore creates a new database. The original is left untouched.
  2. In UTC.

How far back you can go

Data Restore point
PostgreSQL Any moment
A volume The moment of each backup

Restoring a volume needs an operator