Skip to Content
Technical ReferenceBackup and Restore

Backup and Restore

The export procedure below has been executed against a live deployment, not merely written down. The verification step exists because a backup nobody has restored is not a backup.

Taking a backup

npx convex export --path snapshot.zip

For production:

npx convex export --prod --path snapshot-prod.zip

To include uploaded files — school logos, profile images, safeguarding certificates:

npx convex export --prod --include-file-storage --path snapshot-prod.zip

Without --include-file-storage the archive contains data only. Restoring it gives you a working system with broken images and missing documents.

What is in the archive

A snapshot of this system contains 28 tables, including:

  • users, schools, leagues
  • tournaments, teams, rounds, debates
  • judging_scores — every ballot
  • ranking_snapshots, school_tiers
  • payments, audit_logs
  • _components — the workpool, cache and retrier state

Verify an archive before trusting it:

python -c "import zipfile; z=zipfile.ZipFile('snapshot.zip'); print(len(z.namelist()), 'entries')"

An archive with only a handful of entries did not export properly.

Restoring

Restore to a scratch deployment first

Never restore straight into production. Create or reuse a development deployment and restore there.

npx convex import snapshot.zip

Check the restore

Sign in and confirm:

  • A tournament you know exists, with its teams
  • A submitted ballot, with its speaker scores intact
  • Rankings, if any were released

Only then restore to production

npx convex import --prod --replace-all snapshot-prod.zip

The import modes

FlagEffect
--appendAdds to existing tables
--replaceReplaces the tables present in the archive
--replace-allReplaces everything, deleting tables absent from the archive

--replace-all is the correct choice for disaster recovery and the wrong choice for anything else.

How often

  • Before any schema change or major deploy — always
  • Before and after every tournament — a tournament’s ballots cannot be reconstructed from memory
  • Weekly during an active season

Keep at least one backup off the machine that made it.

What a backup does not cover

Environment variables are not in the archive. Record them separately:

npx convex env list

A restore into an empty deployment with no environment variables will start but will not send email, deliver push notifications, or reach Gemini.

Recovery checklist

  1. Restore the data with --replace-all
  2. Set every environment variable from Environment Variables
  3. Redeploy the frontend
  4. Sign in and check a tournament, a ballot, and the rankings
  5. Send one test email to confirm SMTP is configured
Last updated on