Skip to main content

Overview

Genesis on EKS stores all persistent state on a single PersistentVolumeClaim (genesis-data) backed by an EBS volume. Backing up Genesis means taking periodic snapshots of that volume and preserving the Kubernetes Secret that holds the master encryption key. Genesis is a well-behaved StatefulSet tenant: one namespace, one PVC, standard Kubernetes primitives. Any namespace-aware backup tool — Velero, AWS Backup for EKS, Kasten K10, or manual EBS snapshots — works without application-level changes. The one wrinkle is SQLite consistency. Genesis uses multiple SQLite databases in WAL mode, so a raw block-level snapshot of an active volume can capture a mid-transaction state. A short pre-backup hook checkpoints the WAL files to make the snapshot consistent.

Incremental object-store snapshots

For a portable snapshot of the Helm chart’s PVC layout, run the bundled export-state command while the Genesis server is stopped:
The destination can also be a gs:// bucket or a local directory, for example /mnt/backups/<instance>. For an S3 destination, Genesis uses the ambient AWS credential chain (pod identity, instance profile, AWS_PROFILE/SSO, or AWS_* environment variables). For GCS, it uses the ambient Google identity. The S3 region defaults to AWS_REGION, then AWS_DEFAULT_REGION, then us-east-1; omit --kms-key-id to use the AWS-managed S3 key. GCS uses the bucket’s default encryption and does not accept --kms-key-id. To request the same snapshot from a running instance, use the authenticated admin API instead of stopping the server manually. See the state snapshot admin endpoints for the request body, required permissions and example. The API validates the S3 or GCS destination, returns 202 with a job ID, then pauses the instance while the exporter copies its state and restarts the server. Poll the job after the server is back to read the resulting snapshot ID. See State Snapshots and Migration for GCS bucket permissions, Workload Identity, and the API connection fields. Each completed snapshot is stored below the destination in a new snapshot ID:
The layout matches the PVC subpaths above. The manifest is written last, so an incomplete export is ignored. When a previous complete snapshot exists under the same S3 destination, unchanged files are copied server-side and only changed files are uploaded. The export excludes .microapp_venv/, .microapp_home/, and __pycache__/; repository .git directories keep their real name. Genesis refuses to export while its server is running: the SQLite database is copied consistently, and stopping the server keeps the directory trees consistent with that database.

Restoring an object-store snapshot

The Genesis Helm chart can restore a completed object-store snapshot into the genesis-data PVC before the first Genesis container starts. Add the following to your values file:
restore.from accepts either an s3:// or gs:// snapshot path, such as s3://my-bucket/genesis-snapshots/<instance>/<snapshot-id>, or an instance prefix, which selects its newest complete snapshot. The default is "", which disables restore. restore.region defaults to "" and specifies the AWS region for an S3 bucket; it is unused for GCS. restore.resources defaults to {} and optionally sets the restore init container’s Kubernetes resource requests and limits. For GCS, the init container reads with the pod’s Google identity; see State Snapshots and Migration for Workload Identity setup. The restore init container uses the pod’s identity for object-store access, including IRSA on EKS. It receives the master key from the same configuration as the Genesis container: secrets.genesisMasterKey, secrets.existingSecretGenesisMasterKey, or config.extraEnv.GENESIS_MASTER_KEY_REF. The snapshot must use the same master key as the target instance. The restore refuses a different key, an unsupported or newer release snapshot, an invalid signature, any missing, extra, or corrupted file, and a database that fails SQLite’s integrity check. The chart requires an image that includes the restore runner. Release image tags at or below v1.19.93 are rejected during chart rendering when restore.from is set; use a newer image. A tag that is not a plain semantic version is not ordered by the chart, so verify that it includes the restore runner before deploying. The init container only restores an empty volume. If the target already holds Genesis state, it skips the restore on pod startup, including after a restart or upgrade. Failures during discovery, verification, or staging leave the existing volume unchanged, and the init container retries on the next pod start. If a restart interrupts the final tree swap, the next init-container run finishes that verified swap before Genesis starts. To restore again, use an empty PVC, or stop Genesis and run the import runner with --force in a pod that mounts the volume:
Use --runtime-root /app when the snapshot’s source paths were recorded under a different runtime layout, such as a Snowflake SPCS migration. The restore rewrites matching absolute paths as part of staging; see State Snapshots and Migration for the path rewrite behavior and migration workflow.

What lives on the PVC

The genesis-data PVC is mounted at four subpaths: Everything stateful is on this single volume. The container image, ConfigMaps, and environment variables are stateless and reconstructed from the Helm chart.
The master encryption key is not on the PVC. It lives outside the volume — in a Kubernetes Secret as GENESIS_MASTER_KEY, or resolved at startup from AWS/GCP when GENESIS_MASTER_KEY_REF is set — and is required to decrypt connection credentials stored in genesis.db. Restoring the volume without the matching master key renders encrypted fields unusable. Always back up the master key separately — see Backing up the master key.

Backing up the master key

If you deploy with config.extraEnv.GENESIS_MASTER_KEY_REF, the master key already lives in AWS Secrets Manager or GCP Secret Manager. Ensure that secret is included in your organization’s vault backup and rotation policies — you do not need a separate Kubernetes Secret export.
Export and store the master key in a secure location outside the cluster (when it is stored in the chart-managed Kubernetes Secret):
Import the file into your organization’s secrets vault (AWS Secrets Manager, HashiCorp Vault, etc.) and delete the local copy immediately:
If you rotate the master key, update the backup immediately.
If you use External Secrets (AWS Secrets Manager or GCP Secret Manager) for connection credentials, those secrets survive independently of Genesis backups. See External Secrets for details.

SQLite pre-backup hook

Genesis ships a checkpoint script at scripts/sqlite-checkpoint-hook.sh that flushes all SQLite WAL files on the PVC before a snapshot. The script finds every .db, .sqlite, and .sqlite3 file under /app/.genesis/db and /app/bot_storage and runs PRAGMA wal_checkpoint(TRUNCATE) on each. You can run it manually:
Or wire it into your backup tool as a pre-snapshot hook (see examples below).
The checkpoint takes a few seconds at most. It does not stop the application or interrupt running conversations. It flushes pending writes from WAL files into the main database files so the on-disk state is self-consistent.

Backup tool setup

Prerequisites

  • Velero installed in the cluster with the AWS plugin
  • An S3 bucket for backup storage
  • The EBS CSI driver installed (required for CSI snapshots)

Configure pod annotations

Add Velero backup hook annotations to your Helm values.yaml:
Upgrade the release:

Create a backup schedule

This takes a daily backup at 02:00 UTC and retains backups for 30 days.

Manual backup

Restore

After the restore completes, the Genesis pod restarts automatically against the restored PVC. Verify with:

Recovery checklist

After restoring from any backup method:
  1. Verify the pod is running:
  2. Check database integrity:
  3. Verify the master key matches: If the Kubernetes Secret was also restored, confirm it contains the correct GENESIS_MASTER_KEY. If you use GENESIS_MASTER_KEY_REF, confirm the referenced AWS/GCP secret still exists and the pod’s IRSA/ADC identity can read it. If restoring into a new cluster, recreate the Secret or GENESIS_MASTER_KEY_REF configuration from your vault backup.
  4. Check the application health endpoint:
  5. Verify data: Log into the Genesis UI and confirm agents, threads, and connections are present.
Genesis includes automatic SQLite corruption detection and recovery (sqlite_recovery_core.py). If the database is slightly inconsistent after a restore, Genesis will attempt to repair it on startup.

RPO and RTO guidance

To reduce RPO impact:
  • Blueprints and missions can be re-deployed from source control
  • Connections require the master key; with it, they restore fully from the PVC backup
  • External secrets (AWS Secrets Manager / GCP Secret Manager) survive independently

Supplemental: configuration export

genesis config export exports Genesis configuration to a YAML or JSON file that can be version-controlled independently of PVC backups:
This captures system configuration but not thread history, uploaded files, or connection credentials.