infra/scripts/backup.sh, restore.sh, restore-drill.sh), not as a managed
backup service. This page states what those scripts do today, plainly,
including the gaps — a number nobody would act on if it turned out to be
wrong is worse than no number at all.
What is backed up
PostgreSQL, including roles and privileges. Apg_dump of the schema and
its data, plus a separate pg_dumpall --roles-only of the cluster’s login
roles. Both matter: the application connects as narrow, non-superuser roles
(trustowl_app_login, trustowl_job_login) that row-level security binds,
and those roles are cluster objects a plain database dump does not carry.
Restoring the data without them produces a database RLS does not enforce, or
one every query is refused against — see
Data protection for why the role matters this
much.
Encrypted before it leaves the host that took it, to a recipient — the
production host holds no key that can decrypt its own backups. Redis is
not backed up. It holds queue state and rate-limit counters, both
reconstructable, never a customer’s security findings.
What is not backed up, or not yet proven
- Off-host storage has been drilled only against a local
rclonetarget, not a real S3-compatible bucket with production credentials. Until that drill runs against real object storage, treat the off-host copy as configured but unproven in your environment. - The
agedecryption identity’s storage location is an operator decision, documented as needing to live off the production host. Nothing in the software enforces that placement — verify it in your own deployment. - The Kubernetes / managed-Postgres deployment path has no backup gate wired into it today. The Compose deployment path does; a managed Postgres provider’s own backup and PITR features are the appropriate substitute if you deploy that way, and are not something TRUSTIVAN configures for you.
RPO and RTO, as shipped
Neither number has been validated against production traffic or production
infrastructure — both are measured against a local drill. Treat them as
engineering targets you re-verify in your own environment, not as an SLA.
The restore drill, and what it proves
restore-drill.sh restores from the off-host copy into a new database (never over a live one), and checks, in order:
- The schema version matches what the restoring build expects.
tenant_isolationpolicies exist on the restored tables.- Per-role grants exist for both the application and job-plane roles — a restore that carries the data and the policies but not the privileges produces a database that refuses every query, which looks identical to “the restore worked” until the first request.
Retention
Local encrypted backups are pruned afterBACKUP_RETENTION_DAYS (default 30).
Off-host retention is not currently governed by this tooling — set a
lifecycle rule on whatever object storage you configure.
See also
- Data map — what is stored, encrypted or not, and for how long, independent of backups.
- Environment configuration —
BACKUP_DIR,BACKUP_PUBLIC_KEY,BACKUP_REMOTE,BACKUP_RETENTION_DAYS.

