Deployment Topology
This page draws the Kubernetes deployment two ways: what the Helm chart renders today, and what the high-availability epic (#3408) plans to add. They are separate diagrams on purpose. Nothing in the second one is in the chart today, and a single diagram would make it look as though it is.
Use it with Deployment to install, Backup & Restore to recover, and Durability & Redundancy for what each failure costs.
Ships today
Section titled “Ships today”The chart renders six long-running workloads (web, api, celery-worker, celery-beat, PostgreSQL and Valkey), plus three optional pieces: the Ingress, the media PVC and the backup CronJob. The object-storage bucket is yours to provide. Everything below is verified against packages/helm/templates/ and values.yaml.
Solid boxes are rendered by a default install. Dashed boxes are opt-in or something you supply. Two things the diagram deliberately does not draw because the chart does not render them: there is no separate WebSocket (Channels) deployment, since the api pod runs uvicorn trueppm_api.asgi:application and serves REST and WebSocket together; and there is no migration Job, since each api pod runs migrate_locked as an init container, which serializes concurrent pods on an advisory lock.
What the chart does and does not give you
Section titled “What the chart does and does not give you”- One PostgreSQL pod, one Valkey pod. The bundled sub-charts are single-replica StatefulSets with
ReadWriteOncePVCs. They survive a container restart because the data is on the volume. If the pod is lost it is an outage until Kubernetes reschedules it onto the same volume, and data is at risk only if that volume was node-local storage on a lost node (see the failure-mode matrix). Because/api/v1/readyzchecks a live cache round-trip, losing Valkey marks everyapipodNotReady. See Valkey High Availability. - No point-in-time recovery and no in-cluster HA today. The chart has no WAL archiving, so recovery is to the last logical backup. The production overlay (
values-prod.yaml) disables both sub-charts and pointsDATABASE_URLandREDIS_URLat managed services; that is the supported way to get HA or PITR today. replicaCountscalesapi,celery-workerandweb, notcelery-beat. Beat is pinned to one replica, because a second one double-fires every periodic task.- The
webpod is the front door. With the Ingress path split invalues.yaml,/goes toweband/apiand/wsgo straight toapi. Thewebpod also proxies/api/and/ws/toapi. - The demo seed Job and demo reset CronJob exist only when
demo.enabledis set, and are left out.
What a backup and restore must cover
Section titled “What a backup and restore must cover”| Data | Where it lives | In the chart’s backup? |
|---|---|---|
| Application database | PostgreSQL volume (8Gi PVC on the bundled sub-chart, or your managed database) | Yes. The CronJob runs pg_dump --format=custom. |
PostgreSQL extensions ltree, pg_trgm, btree_gist | Created in the database by the application’s migrations | Preserved by the custom-format dump. A managed database must allow them. A restore fails loudly if they are missing. |
Everything written to the media volume: attachments, the workspace logo, seed-import payloads and the project, program and workspace export bundles (six write paths, listed at persistence.media in values.yaml) | The media PVC if you use local storage, otherwise the object-storage bucket | Media PVC: only if you set backup.mediaDir and mount the claim read-only. A ReadWriteOnce claim is readable by the backup Job only if the Job lands on the same node as the api pod that holds it, which is one reason the default is ReadWriteMany. Bucket: no, back it up with the object store’s own tooling. |
| Valkey (broker, Channels layer, cache, throttle counters) | Valkey volume (2Gi PVC, AOF) | No, by design. It holds reconstructible state only. |
INTEGRATION_ENCRYPTION_KEY and the other application Secrets | Kubernetes Secret | No. The dump is useless without the key, so back it up separately. |
| Backup artifacts | The backup PVC, an S3-compatible bucket, or both | They are the output, not an input. The chart refuses to render an enabled backup with nowhere durable to write. |
The backup is off by default (backup.enabled: false). Restores are manual, using scripts/restore.sh; see Backup & Restore for the runbook and the restore drill.
Planned HA topology
Section titled “Planned HA topology”This diagram draws only the planned datastore changes, so the application tier is shown as it is today. The epic also plans changes that are not drawn: a connection-pooling path (#2275), separate Celery queues with queue-depth worker autoscaling (#2276), and a single application Secret contract with an ExternalSecret template (#3405). Any of these may change the paths between the application tier and the datastores.
Dashed boxes are planned. In this diagram only the application tier exists today. The Ingress, media PVC, object storage and backup paths are not redrawn; they are unchanged from Ships today.
This is the single-cluster line: surviving the loss of a pod or node inside one cluster. It does not survive the loss of the cluster or the region. Cross-region replication, geo failover and managed backup verification are Enterprise features and are not drawn here.
A few things to plan around:
- Managed services remain fully supported and are the way to get HA or PITR today. Nothing in the planned work removes that option.
- How the logical backup relates to WAL archiving is undecided. #3403 will decide it, including whether the backup CronJob stays as it is once WAL archiving is on. Until then, the dump-and-restore runbook above is the supported recovery path, and Valkey is not part of any backup.
- Sentinel client support already exists, but no Sentinel nodes are deployed. The chart can be pointed at Sentinels you run yourself (
valkey.sentinel, experimental). What is planned is the chart standing up a replicated Valkey with automatic failover for you; the roadmap plans Sentinel, while #3404 still weighs a Valkey operator as the alternative.