PostgreSQL is the system of record. It stores projects, model and spec content, versioning history, and — when Keycloak uses it — identity data. This is the one component you must back up.
Role in the stack
Studio reads and writes application data here, and the Yjs Realtime Server persists collaboration documents into it. It is the durable heart of the stack.
PostgreSQL is stateful: it needs stable storage and a stable network
identity, so it is deployed as a StatefulSet (Kubernetes) or a single-node
pinned service with a named volume (Swarm).
apiVersion: apps/v1kind: StatefulSetmetadata: name: postgres namespace: iomodelspec: serviceName: postgres replicas: 1 selector: { matchLabels: { app: postgres } } template: metadata: { labels: { app: postgres } } spec: containers: - name: postgres image: postgres:16 ports: [{ containerPort: 5432 }] volumeMounts: - name: pgdata mountPath: /var/lib/postgresql/data volumeClaimTemplates: - metadata: { name: pgdata } spec: accessModes: ['ReadWriteOnce'] resources: { requests: { storage: 20Gi } }The volumeClaimTemplates block is what makes storage durable and bound to
the pod identity. Never run the database off an emptyDir.
Back it up and test restores
A backup you have not restored is a hope, not a plan. Schedule regular dumps or volume snapshots with retention, and rehearse restores.
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: postgres
namespace: iomodel
spec:
serviceName: postgres
replicas: 1
selector: { matchLabels: { app: postgres } }
template:
metadata: { labels: { app: postgres } }
spec:
containers:
- name: postgres
image: postgres:16
ports: [{ containerPort: 5432 }]
volumeMounts:
- name: pgdata
mountPath: /var/lib/postgresql/data
volumeClaimTemplates:
- metadata: { name: pgdata }
spec:
accessModes: ['ReadWriteOnce']
resources: { requests: { storage: 20Gi } }