> ## Documentation Index
> Fetch the complete documentation index at: https://radarhq.io/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Backups

> What's recoverable from K8s state alone, and what needs Postgres backups.

## The TL;DR

Back up Postgres. The chart itself is stateless.

## What lives where

| Data                                                  | Location                          | Recoverable from K8s?                                       |
| ----------------------------------------------------- | --------------------------------- | ----------------------------------------------------------- |
| Cluster registrations (id, name, token hash, status)  | Postgres                          | ❌                                                           |
| Org members + roles                                   | Postgres                          | ❌                                                           |
| Audit log                                             | Postgres                          | ❌                                                           |
| Personal Access Token hashes                          | Postgres                          | ❌                                                           |
| Notification destinations                             | Postgres                          | ❌                                                           |
| Inbox (in-app notifications)                          | Postgres                          | ❌                                                           |
| Session cookies (sealed in browsers)                  | N/A                               | tied to `HUB_COOKIE_PASSWORD` - rotating signs everyone out |
| Tunnel sessions to in-cluster Radar                   | In-memory on the `radar-hub` Pod  | ✅ - reconnect on Pod restart                                |
| Cluster-side resource state (Pods, Deployments, etc.) | The customer's own kube-apiserver | ✅ - never copied to the control plane                       |

The control plane holds **no** customer cluster data. Helm catalog / package state, audit findings, topology - all of that lives in the customer's own etcd / Radar's per-cluster cache. Restoring the control plane means restoring its Postgres + redeploying the chart; tunnels reconnect within seconds.

## Backup recipe (managed Postgres)

Use whatever your provider offers - RDS automated backups, Cloud SQL exports, Azure Flexible Server PITR. Set retention to your compliance requirement.

## Backup recipe (CloudNativePG)

```yaml theme={null}
# In the same namespace as the CNPG Cluster
apiVersion: postgresql.cnpg.io/v1
kind: ScheduledBackup
metadata:
  name: radar-hub-pg-daily
spec:
  schedule: "0 2 * * *"   # 02:00 UTC daily
  cluster:
    name: radar-hub-pg
  immediate: false
```

CNPG handles the rest - snapshots land in the object store you configured for the cluster.

## Backup recipe (hand-rolled `pg_dump`)

Cron'd from anywhere with network access to the DB:

```bash theme={null}
PGPASSWORD=<pw> pg_dump -h <host> -U radar -Fc radar_hub > /backups/radar-hub-$(date +%Y%m%d).dump
```

Restore:

```bash theme={null}
# 1. Stop the control plane so writes don't race.
kubectl -n radar-hub scale deploy/radar-hub-hub --replicas=0

# 2. Drop + recreate the database (or point a new install at a fresh DB).
PGPASSWORD=<pw> psql -h <host> -U radar -c "DROP DATABASE radar_hub" -d postgres
PGPASSWORD=<pw> psql -h <host> -U radar -c "CREATE DATABASE radar_hub" -d postgres

# 3. Restore.
PGPASSWORD=<pw> pg_restore -h <host> -U radar -d radar_hub /backups/radar-hub-20260510.dump

# 4. Bring it back up.
kubectl -n radar-hub scale deploy/radar-hub-hub --replicas=1
```

## What you DON'T need to back up

* `helm get values radar-hub --namespace radar-hub` - check this into your IaC repo and you can re-derive the install. (Strip secrets first - those should already be in your Secret manager.)
* The Helm chart itself - we publish it on a versioned repo; pin the `appVersion` in your IaC and `helm upgrade` re-creates everything.
* Container images - re-pulled from `ghcr.io` on every Pod start.

## Restore drill (recommended quarterly)

A backup you haven't tested isn't a backup.

1. Spin up a side-by-side install in a separate namespace pointed at a fresh empty DB.
2. Restore your latest backup into that DB.
3. Sign in as the break-glass admin. Confirm the cluster list, member roster, and audit log look correct.
4. Tear down. Net result: confidence + a dated record that the procedure works.

## What's NOT backed up by Skyhook

In a self-hosted install Skyhook has no access to your data. Your Postgres backups, your problem.

If you're running the hosted Cloud at `app.radarhq.io`, that's our problem - see [Cloud Operations](/docs/cloud/billing) for the SaaS DR posture. Self-hosted explicitly delegates this to you.
