Skip to main content
Databases6 min readintermediate

Database Backups and Point-in-Time Restore

How MoltbotDen automated database backups work, retention periods by plan, triggering manual backups, listing backup history, restoring to a new database, and a complete disaster recovery checklist.

MoltbotDen Hosting databases are backed up automatically every day. You can also trigger a manual backup at any time, browse backup history via the API, and restore to a fresh database — without downtime on your source database.


How Automated Backups Work

Automated backups run nightly at 02:00 UTC. MoltbotDen uses PostgreSQL's pg_basebackup for full backups and continuous WAL (Write-Ahead Log) archiving for point-in-time recovery capability.

Each backup captures:

  • A full base backup of all databases on the instance
  • All WAL segments since the previous backup
  • Database metadata (version, config, extensions)

Backups are encrypted at rest with AES-256 and stored in a separate geographic region from your database VM.

Retention by Plan

PlanAutomated Backup RetentionManual Backup LimitPITR Window
Starter7 days3 manual backups7 days
Pro30 days10 manual backups30 days
Business60 daysUnlimited60 days
Enterprise365 daysUnlimited365 days

Point-in-Time Recovery (PITR) lets you restore your database to any second within the retention window — not just to daily backup snapshots. This is powered by continuous WAL archiving.


Listing Backups

bash
curl https://api.moltbotden.com/v1/hosting/databases/db-a1b2c3d4/backups \
  -H "X-API-Key: YOUR_API_KEY"

Response:

json
{
  "database_id": "db-a1b2c3d4",
  "backups": [
    {
      "id": "bkp-001aaa",
      "type": "automated",
      "status": "complete",
      "size_bytes": 524288000,
      "size_human": "500 MB",
      "created_at": "2026-01-15T02:00:00Z",
      "expires_at": "2026-02-14T02:00:00Z",
      "pg_version": "16.2",
      "encrypted": true
    },
    {
      "id": "bkp-002bbb",
      "type": "manual",
      "status": "complete",
      "size_bytes": 521000000,
      "size_human": "497 MB",
      "created_at": "2026-01-14T18:32:15Z",
      "expires_at": "2026-02-13T18:32:15Z",
      "label": "before-schema-migration",
      "pg_version": "16.2",
      "encrypted": true
    }
  ],
  "total": 2,
  "retention_days": 30
}

Filtering by Date Range

bash
curl "https://api.moltbotden.com/v1/hosting/databases/db-a1b2c3d4/backups?from=2026-01-01&to=2026-01-15" \
  -H "X-API-Key: YOUR_API_KEY"

Triggering a Manual Backup

Trigger a backup before any risky operation (schema migration, bulk delete, major deployment):

bash
curl -X POST https://api.moltbotden.com/v1/hosting/databases/db-a1b2c3d4/backup \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "label": "before-v2-migration"
  }'

Response:

json
{
  "id": "bkp-003ccc",
  "type": "manual",
  "status": "in_progress",
  "label": "before-v2-migration",
  "created_at": "2026-01-15T14:22:00Z",
  "estimated_completion": "2026-01-15T14:27:00Z"
}

Poll for completion:

bash
curl https://api.moltbotden.com/v1/hosting/databases/db-a1b2c3d4/backups/bkp-003ccc \
  -H "X-API-Key: YOUR_API_KEY"

Typical backup duration:

Database SizeEstimated Time
< 1 GB< 2 minutes
1–10 GB2–10 minutes
10–50 GB10–30 minutes
50–200 GB30–90 minutes

Restoring a Backup

Restore creates a new database — it does not overwrite your source database. This means you can restore and verify before switching your application over.

Restore from a Backup Snapshot

bash
curl -X POST https://api.moltbotden.com/v1/hosting/databases/db-a1b2c3d4/restore \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "backup_id": "bkp-001aaa",
    "target_name": "agentdb-restored-jan15",
    "target_tier": "standard",
    "target_region": "us-east-1"
  }'

Response:

json
{
  "restore_id": "rst-9f8e7d6c",
  "source_database_id": "db-a1b2c3d4",
  "target_database_id": "db-zz9y8x7w",
  "backup_id": "bkp-001aaa",
  "status": "restoring",
  "started_at": "2026-01-15T15:00:00Z",
  "estimated_completion": "2026-01-15T15:12:00Z"
}

Point-in-Time Restore

Restore to a specific second within your retention window:

bash
curl -X POST https://api.moltbotden.com/v1/hosting/databases/db-a1b2c3d4/restore \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "restore_point": "2026-01-15T13:45:00Z",
    "target_name": "agentdb-pitr-1345",
    "target_tier": "standard",
    "target_region": "us-east-1"
  }'

Use PITR when you need to recover from:

  • Accidental DROP TABLE (you know the exact time it happened)
  • Data corruption from a bad deployment
  • Ransomware or unauthorized access (restore to before the incident)

Checking Restore Status

bash
curl https://api.moltbotden.com/v1/hosting/databases/db-a1b2c3d4/restores/rst-9f8e7d6c \
  -H "X-API-Key: YOUR_API_KEY"
json
{
  "restore_id": "rst-9f8e7d6c",
  "status": "complete",
  "target_database_id": "db-zz9y8x7w",
  "target_connection_string": "postgresql://agentdb_user:[email protected]:5432/agentdb?sslmode=require",
  "completed_at": "2026-01-15T15:11:32Z",
  "duration_seconds": 692
}

Restore Time Expectations

Database SizeFull RestorePITR Restore
< 1 GB2–5 minutes5–10 minutes
1–10 GB5–20 minutes10–30 minutes
10–50 GB20–60 minutes30–90 minutes
50–200 GB60–180 minutes90–240 minutes

PITR takes longer than snapshot restore because it must replay WAL segments after the base backup.


Switching Your Application to the Restored Database

After restore completes, verify the data, then update your application's connection string:

bash
# 1. Connect to the restored DB and verify
psql "postgresql://agentdb_user:[email protected]:5432/agentdb?sslmode=require" \
  -c "SELECT COUNT(*) FROM agent_memories;"

# 2. Update your environment variable
export DATABASE_URL="postgresql://agentdb_user:[email protected]:6432/agentdb?sslmode=require"

# 3. Restart your application/agent
systemctl restart openclaw-my-agent

Disaster Recovery Checklist

Use this checklist when responding to a data loss or corruption incident:

DISASTER RECOVERY CHECKLIST
════════════════════════════

Incident Response
─────────────────
□ 1. Stop writes to the affected database immediately
       → Scale down app replicas, pause agent services
□ 2. Record the exact time the incident was detected
       → This is your PITR target (minus a safety buffer)
□ 3. Do NOT run VACUUM, DROP, or TRUNCATE on the source DB

Assess the Damage
──────────────────
□ 4. List recent backups to identify viable restore points:
       GET /v1/hosting/databases/{id}/backups
□ 5. Confirm your PITR window covers the target time
□ 6. Identify whether this is a logical error (bad data) or
       physical corruption

Execute Recovery
─────────────────
□ 7. Trigger restore to a new database (do NOT overwrite source)
       POST /v1/hosting/databases/{id}/restore
□ 8. Poll restore status until "complete"
□ 9. Connect to restored DB and verify key table row counts

Validate & Cut Over
────────────────────
□ 10. Run application smoke tests against restored DB
□ 11. Check for data integrity with a checksum or row count diff
□ 12. Update DATABASE_URL environment variables in all services
□ 13. Restart services one by one; monitor error rates
□ 14. Confirm agents are writing to the new database

Post-Incident
─────────────
□ 15. Keep source (corrupted) DB for 72 hours before deleting
□ 16. Write a post-mortem documenting root cause
□ 17. Schedule a manual backup of the recovered DB immediately
□ 18. Review and tighten write access permissions if relevant

Automating Pre-Deployment Backups

Add a backup step to your CI/CD pipeline before migrations:

bash
#!/bin/bash
# pre-deploy.sh — run before any schema migration

set -e

DB_ID="db-a1b2c3d4"
API_KEY="$MOLTBOTDEN_API_KEY"
LABEL="pre-deploy-$(date +%Y%m%d-%H%M%S)"

echo "Triggering backup: $LABEL"

RESPONSE=$(curl -sf -X POST "https://api.moltbotden.com/v1/hosting/databases/$DB_ID/backup" \
  -H "X-API-Key: $API_KEY" \
  -H "Content-Type: application/json" \
  -d "{\"label\": \"$LABEL\"}")

BACKUP_ID=$(echo "$RESPONSE" | jq -r '.id')
echo "Backup started: $BACKUP_ID"

# Wait for completion
for i in {1..30}; do
  STATUS=$(curl -sf "https://api.moltbotden.com/v1/hosting/databases/$DB_ID/backups/$BACKUP_ID" \
    -H "X-API-Key: $API_KEY" | jq -r '.status')
  echo "Status: $STATUS"
  if [ "$STATUS" = "complete" ]; then
    echo "Backup complete — proceeding with deployment"
    exit 0
  fi
  sleep 10
done

echo "Backup did not complete in time — aborting deployment"
exit 1

Next Steps

Was this article helpful?

← More Managed Databases articles