Skip to main content
Restore downloads a snapshot and inserts its data into a target database. It validates schema compatibility and ensures referential integrity during the process.
Run your migrations first. Restore validates the target schema and inserts data; it does not create or alter tables.

Usage

basecut snapshot restore <snapshot-ref> [flags]

Arguments

ArgumentDescription
<snapshot-ref>Snapshot identifier. Supported forms: UUID, name:tag, or name (resolves to latest).

Flags

FlagDefaultDescription
--target <url>, -t$BASECUT_TARGET_DATABASE_URLPostgreSQL connection string for the destination database. Restore does not use BASECUT_DATABASE_URL so you do not accidentally restore over your source.
--resetfalseTruncate snapshot-managed tables before applying (destructive).
--forcefalseSkip schema validation (may fail if schemas are incompatible).
--batch-size <n>1000Rows per insert batch (auto-capped per table by database limits).
--on-conflict <mode>errorConflict behavior: error (fail fast) or skip (ignore conflicts).
--analyze-fksfalseRun FK preflight analysis only (no data is applied).
--unsafe-disable-fk-checksfalseUnsafe bypass: disables FK checks during restore (requires elevated DB privileges).
--yes, -yfalseSkip confirmation prompts.
--profile <name>defaultCredential profile to use for API authentication.
--api-key <key>$BASECUT_API_KEYAPI key override (otherwise uses BASECUT_API_KEY or saved profile).

Examples

Quick Examples

# Restore the latest version of a snapshot
basecut snapshot restore my-snapshot:latest \
  --target "postgresql://localhost:5432/myapp_test"

# Restore a specific version with a reset
basecut snapshot restore my-snapshot:brave-lion \
  --target "$BASECUT_TARGET_DATABASE_URL" \
  --reset

# Restore while skipping duplicate key conflicts
basecut snapshot restore my-snapshot:latest \
  --target "$BASECUT_TARGET_DATABASE_URL" \
  --on-conflict skip

Basic Restore

Apply the latest version of a snapshot to your local database:
basecut snapshot restore "weekly-dev-data" \
  --target "postgresql://localhost:5432/myapp_dev"
What happens:
  1. CLI resolves the latest tag for “weekly-dev-data”.
  2. Downloads manifest and schema metadata.
  3. Connects to the target database and validates schema compatibility.
  4. Downloads data files and inserts rows in dependency order.
  5. Verifies referential integrity across all restored tables.

Clean Restore (Local Development)

Wipe existing data in the target tables before restoring:
basecut snapshot restore "clean-seed" \
  --target "postgresql://localhost:5432/myapp_dev" \
  --reset \
  --yes
When to use --reset:
  • You want to ensure the target tables only contain the snapshot data.
  • You are re-running a seed script and want to avoid duplicate key errors.
  • You want a clean slate for debugging a specific issue.
--reset runs inside the same transaction as restore inserts. If restore fails, all reset and insert operations are rolled back together.

CI/CD Integration

Automate restoration for integration tests:
export BASECUT_API_KEY=bc_live_abc123_secret
export BASECUT_TARGET_DATABASE_URL=postgresql://test_user:pass@localhost:5432/test_db

basecut snapshot restore "ci-baseline:latest" --yes

Analyze Foreign Key Restore Safety

Preview FK-related restore risk before applying any data:
basecut snapshot restore "production:latest" \
  --target "$BASECUT_TARGET_DATABASE_URL" \
  --analyze-fks
--analyze-fks reports:
  • Number of non-deferrable foreign key constraints.
  • Self-referential tables in the restore scope.
  • Whether an inter-table FK cycle exists.
  • Whether safe restore mode would be blocked.
  • Whether nullable fallback is available for blocking constraints.
If Nullable fallback available: true, Basecut will automatically handle the restore using a two-phase approach — inserting rows with temporary NULLs for the blocking FK columns, then backfilling the real values — with no additional flags required. This requires that all blocking FK columns are nullable and the affected table has a primary key or unique key. Use this when preparing migrations or debugging FK restore blockers.

Unsafe FK Bypass (Last Resort)

If you need a one-off restore and cannot make constraints deferrable immediately:
basecut snapshot restore "production:latest" \
  --target "$BASECUT_TARGET_DATABASE_URL" \
  --unsafe-disable-fk-checks
--unsafe-disable-fk-checks disables FK enforcement during restore. Use only in controlled environments and validate integrity after restore.
This mode may require elevated PostgreSQL privileges.

Output

Success

 Loading snapshot: my-snapshot:brave-lion
 Validated schema for 23 tables
 Inserted 2,847 rows
 Verified referential integrity
 Restore complete in 3.2s

With Reset

 Truncating 23 tables...
 Loading snapshot: my-snapshot:latest
 Validated schema for 23 tables
 Inserted 2,847 rows
 Restore complete

Error Handling

Schema Compatibility Error

✗ Error: schema mismatch detected
  Table 'users' is missing column 'last_login_at' which is present in snapshot.
Solutions:
  • Run your database migrations to align the target schema with the snapshot.
  • Use --force to skip validation (not recommended if data types have changed).

Foreign Key Constraint Error

✗ Error: foreign key violation during restore on orders (orders_user_id_fkey)
Common causes:
  • Non-deferrable foreign keys combined with cyclic or self-referential dependencies.
  • Parent rows missing from target scope while child rows are restored.
Solutions:
  • Run FK preflight first:
    basecut snapshot restore "<snapshot-ref>" --target "$BASECUT_TARGET_DATABASE_URL" --analyze-fks
    
  • Make relevant foreign key constraints DEFERRABLE where appropriate.
  • If --analyze-fks reports nullable fallback available, re-run restore normally — Basecut handles it automatically. Note: nullable fallback is not compatible with --on-conflict skip; use the default conflict policy.
  • Ensure referenced parent tables/rows are included in the snapshot.
  • If you need a temporary bypass, use --unsafe-disable-fk-checks (unsafe).
  • Re-run after schema alignment or adjust restore scope.

Conflict Error (--on-conflict error)

✗ Error: duplicate key value violates unique constraint ...
Solutions:
  • Use --reset for a clean restore target, or
  • Use --on-conflict skip to continue and skip conflicting rows.

Connection Failed

✗ Error: failed to connect to target database
  dial tcp 127.0.0.1:5432: connect: connection refused
Solutions:
  • Verify the target database is running.
  • Check the connection string and credentials.
  • Ensure the database is accessible from your network.

Next Steps

Create Snapshot

Learn how to extract data from your source database

Snapshots Concept

Understand the anatomy and lifecycle of snapshots

Snapshot Versioning

Learn how tags and versions work

Troubleshooting

Common issues and how to solve them