Skip to content
Beta — Truss is in public beta. Documentation is actively updated but may not reflect the latest changes. Report issues on GitHub.

High Availability

Truss talks to Postgres over a single DATABASE_URL. That means HA is a property of the Postgres you point it at, not of Truss itself, which is exactly what you want: use whatever database high-availability story you already trust.

Both shipped deployments run a single Postgres instance:

  • Docker Compose (docker-compose.selfhosted.yml) , one postgres container.
  • Helm chart (charts/truss) , one Postgres StatefulSet, replicas: 1.

This is deliberate: it runs anywhere, it’s cheap, and it’s the right default for a homelab, a single VPS, or an evaluation. It has no failover, if that Postgres goes down, Truss is down until it comes back. Take regular backups (see Branching & Backups).

Section titled “Option 1 , managed Postgres (recommended for most)”

The simplest path: don’t self-manage HA at all. Point DATABASE_URL at a managed Postgres (Amazon RDS / Aurora, Cloud SQL, Neon, Supabase, Crunchy Bridge). They handle replication, automatic failover, backups, and PITR for you.

Terminal window
DATABASE_URL=postgres://user:pass@your-managed-host:5432/truss?sslmode=require

Nothing else in Truss changes. This is the least operational burden and the safest choice unless you specifically want to run the database yourself.

Option 2 , run Postgres under an operator (self-managed HA)

Section titled “Option 2 , run Postgres under an operator (self-managed HA)”

If you want HA on your own Kubernetes cluster, run Postgres under a replication operator such as CloudNativePG (CNPG) and point DATABASE_URL at the operator’s read-write Service. CNPG gives you streaming replicas and operator-driven automatic failover with no extra tooling.

# a CloudNativePG Cluster (NOT the Truss chart), e.g. instances: 3
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: truss-postgres
spec:
instances: 3 # 1 primary + 2 streaming replicas

CNPG then manages three Services , *-rw (primary, use this in DATABASE_URL), *-ro (replicas), *-r (any). It also pairs cleanly with a PgBouncer Pooler (type: rw), which follows the primary automatically.

If the primary becomes unhealthy, the operator:

  1. Promotes the most up-to-date replica to primary.
  2. Repoints the -rw Service at the new primary automatically.
  3. Rejoins the old primary as a replica once it recovers.

Because Truss and any pooler connect through the -rw Service (not a pod), they follow the new primary with no config change , a brief blip during promotion, then reconnect.

Replication is asynchronous by default: fast, but a failover can lose the last few transactions that hadn’t reached the promoted replica (a small RPO window). For zero data loss, require a synchronous replica (trades a little write latency):

spec:
instances: 3
postgresql:
synchronous:
method: any
number: 1 # at least one replica must confirm each commit