Almost every database disaster I have seen — including the ones I caused — comes down to touching a production database without a ritual. Here is the checklist I now run before any schema change, migration, or fix. It takes five minutes and has saved me more than once.

The checklist

  1. Stop the service. Not "pause," not "I will be quick." Stop the process that writes. A single write during a migration can corrupt the file or your assumptions.
  2. Take a backup with VACUUM INTO. While stopped, or while running — but take it before you change anything:
    VACUUM INTO 'pre-change-2026-08-26.db';
    
  3. Work on a copy, never the live file. Copy the backup to a scratch location and do the risky work there. Verify the outcome before it touches production.
  4. Verify the result. Run PRAGMA integrity_check and compare row counts with a query. "It ran without error" is not the same as "the data is correct."
  5. Swap deliberately. Only after verification, bring the change into production in the smallest step, then restart the service and smoke-test.
  6. Keep the pre-change backup. Delete it only after the change has been running healthily for a while — or better, keep it in the rotation.

Why each step exists

  • Step 1 prevents the "malformed database" class of bugs — writes landing mid-change.
  • Step 2 gives you a time machine. Without it, a bad change is irreversible.
  • Step 3 keeps the failure contained. You learn everything you need on a copy.
  • Step 4 catches silent damage. integrity_check checks structure, not content — compare data too.
  • Step 5 keeps the blast radius small.
  • Step 6 means your "oops" has a door back.

None of this is clever. It is the boring version of "be careful," written down so that at 2am, under pressure, I do it anyway.

Sizing databases before you build them — so this ritual has less to fear — starts with the estimator below.

Estimated database size436.2 MB
Raw data + indexes370.0 MB
Approx. pages (4 KiB)111662