Github|...

Backups

Create, list and restore database snapshots, and schedule them to run automatically.

Sp00ky Cloud takes care of your backups for you. Make a snapshot whenever you want, set up a schedule, and roll back to any backup when you need to.

Quick Start

# Create a backup
spky backup create

# List all backups
spky backup list

# Restore from a backup
spky backup restore <backup-id>

Creating Backups

Make a backup of your database whenever you want one.

# Create a backup
spky backup create

# Create a named backup
spky backup create --name before-migration

Backups run in the background. The CLI returns right away with a backup ID and a pending status. It moves to in_progress and then to completed once it’s done.

Listing Backups

spky backup list

You’ll see something like this:

ID                                    STATUS        SIZE        CREATED
--------------------------------------------------------------------------------
before-migration (a1b2c3d4)           completed     12.4 MB     2026-04-08T10:00:00
e5f6a7b8-...                          completed     11.8 MB     2026-04-07T02:00:00
f9g0h1i2-...                          completed     10.2 MB     2026-04-06T02:00:00

Restoring from a Backup

spky backup restore <backup-id>

Here’s what happens when you run it:

  1. The scheduler queues the restore and the CLI prints the restore ID.
  2. Ingestion stops. New writes get a 503, and proxy queries and SSP registrations are rejected while the restore is running.
  3. Both databases are wiped and reloaded from the same backup file. Main SurrealDB and the scheduler’s snapshot replica stay in sync.
  4. Pending items are cleared. That covers the in-memory event buffer, the write-ahead log, and any per-SSP message buffers.
  5. Connected SSPs are evicted. They’ll re-register on their next heartbeat against the restored state.
  6. Sp00ky Cloud gives the restored database’s access methods new signing keys and checks that no forged token gets in (see Signing keys after a restore). Only then is the restore reported as done.
  7. The CLI polls for progress every 5 seconds (up to 5 minutes) and shows the current phase as it moves from queued to running to completed.
  8. Once the restore finishes, your migrations run again against the restored database.
Warning

Restoring replaces your current data with the backup. Anything you wrote after the backup was taken is gone. If you’re not sure, take a fresh backup first.

Pay-as-you-go projects

A pay-as-you-go project has no scheduler, so Sp00ky Cloud takes and restores its backups itself, with the same commands and the same backup files. A restore wipes the database, imports the backup and reloads the sync engine, which picks up the restored data on its own; run your migrations again afterwards as above.

To change SurrealDB version, use spky db upgrade, not a backup and restore: it keeps everyone signed in, and takes a backup of its own first.

Signing keys after a restore

Every restore, on VMs and on pay as you go, gives each record DEFINE ACCESS a new signing key, so everyone signed in has to sign in again. SurrealDB’s export does not contain the keys (it writes '[REDACTED]'), and a database restored with that placeholder would let anyone sign a valid token for any user. Sp00ky Cloud checks the restored database after every restore, whatever scheduler version imported it, and refuses to report a restore as done until no access accepts such a token.

Two kinds of access cannot get their key back. Admin impersonation (_00_impersonate) works again after your next spky deploy, which sets its key. An access that verifies tokens of an outside issuer with a shared key is removed by the restore: run its DEFINE ACCESS statement again afterwards (the restore’s metadata names it).

Note

If the main database gets wiped but the snapshot replica fails to import, the scheduler stays in the restoring state on purpose. That blocks reads until someone re-runs the restore. Serving traffic from a half-restored cluster would give back wrong data.

From the dashboard

The scheduler’s admin dashboard has a Backups tab that does everything above except reset: create, list, restore, delete and configure the schedule. It shows the same catalog as spky backup list, joined to what the scheduler itself knows about each backup, and a restore there reports the real stages as the scheduler moves through them (queued, running, main database restored, replica restored, done). It goes through Sp00ky Cloud like spky backup restore, so the signing keys are renewed the same way, and migrations still have to be run again afterwards.

Note

How the dashboard talks to Sp00ky Cloud. The control plane injects SPKY_CLOUD_API_URL and SPKY_CLOUD_PROJECT into the scheduler container (only the scheduler, never the SSPs). The scheduler then calls an allow-listed route family, /v1/internal/projects/{slug}/… (restart, deployment status, and the backup routes minus reset), authenticated with the project’s existing SPKY_AUTH_SECRET. No new credential is created. A control plane that supports this lists scheduler_link under features in its /health response; a scheduler without the link still works and marks those actions as unavailable.

If a backup started from the dashboard fails with Sp00ky Cloud rejected this scheduler’s credentials, that is the control plane refusing the scheduler’s SPKY_AUTH_SECRET, not your login expiring. The dashboard reports it as a 502 carrying the code cloud_auth and keeps you signed in, precisely so the real cause is visible; an earlier version relayed the upstream 401 and signed the operator out instead, which hid it. Check that the project still has a stored auth secret and that the scheduler container was recreated since the secret last changed, then retry. The catalog degrades the same way rather than disappearing: the Backups tab still loads and shows the message where the list would be.

Deleting Backups

spky backup delete <backup-id>

Backups belong to their project: destroying the project deletes all of them.

Automatic Backups

Set up a schedule with a cron expression:

# Enable daily backups at 2 AM, keep last 7
spky backup configure --enabled true --schedule "0 2 * * *" --retention 7

# Disable automatic backups
spky backup configure --enabled false

# Change retention to keep 30 backups
spky backup configure --retention 30
OptionWhat it does
--enabledTurn automatic backups on or off (true/false)
--scheduleCron expression for how often to back up (e.g. "0 2 * * *" for daily at 2 AM)
--retentionHow many backups to keep before the oldest ones get deleted

A pay-as-you-go project is backed up every day at 03:00 UTC and keeps the last 7, until you configure backups yourself. Scheduled backups pause while a project is stopped at its spend cap.

Database Reset

Reset your database to a clean slate. This drops all data and re-runs your migrations.

spky backup reset

The CLI will:

  1. Warn you that all data will be deleted.
  2. Ask you to confirm.
  3. Offer to create a backup first (a good idea).
  4. Wait for that backup to finish if you said yes.
  5. Reset the database and re-apply your migrations.

To skip the pre-reset backup prompt:

spky backup reset --no-backup
Warning

There’s no undo for a reset. Every user, every record, every bit of app data goes away for good. Always take a backup first unless this is a dev project you don’t care about.

CLI Reference

spky backup <COMMAND>

Commands:
  list                          List backups
  create [--name NAME]          Create a manual backup
  restore <backup-id>           Restore database from a backup
  delete <backup-id>            Delete a backup
  configure [--enabled] [--schedule] [--retention]
                                Configure automatic backups
  reset [--no-backup]           Reset the database (drop all data, re-run migrations)