
A successful copy command answers a small question: did some bytes reach a destination? It does not tell you whether those bytes contain a consistent database, or whether the data you care about can be read from them.
We ran an isolated demonstration using Python's SQLite backup API, then opened a restored copy and compared its contents with a baseline. The script creates its own synthetic database. It does not open any production database.
integrity_check = ok, contained 1,001 rows, and matched the baseline content digest. The original contained 1,002 rows after a later commit. This was a local demonstration, not a concurrent-writer stress test.What we actually tested
| Condition | Value |
|---|---|
| Operating system | Windows |
| Python / SQLite | 3.11.9 / 3.45.1 |
| Journal mode | WAL |
| Writer connection | Kept open during backup |
| Concurrent write workload | Not tested |
| Data | Synthetic notes only |
The test ran on November 1, 2026. The exact runtime versions, counts and matching digests are in the downloadable result.
The sequence matters
- Create a new database in a uniquely named experiment directory and enable WAL mode.
- Insert 1,001 synthetic rows, commit, and record an ordered content digest.
- Use
Connection.backup()to write a second database while the source connection remains open. - Commit one more row to the source, after the backup completes.
- Copy the completed backup to a restore-test file and open that file independently.
- Check integrity, row count, and the ordered content digest.
The restored copy correctly contains the earlier 1,001-row state. The later row is absent because it was committed after the backup. This small distinction makes the result easier to interpret than a generic “backup succeeded” message.
Run the isolated example
Download the Python demonstration, inspect it, and choose a new output directory:
python sqlite_backup_demo.py --out ./backup-experiment
Each run creates a unique subdirectory. Python's standard library is enough. Your operating system and SQLite version may differ; the script records them in its result instead of assuming ours.
with sqlite3.connect(source) as writer:
# Commit the state you want to verify first.
with sqlite3.connect(backup) as destination:
writer.backup(destination)
with sqlite3.connect(restored) as checked:
integrity = checked.execute(
"PRAGMA integrity_check"
).fetchone()[0]
Use more than an integrity check
The integrity check asks whether the database's internal structure is consistent. Our row count and digest ask whether this synthetic dataset matches the baseline. A production restore test should also exercise application-specific reads and the permissions, dependencies and steps needed to bring the application back.
For a WAL database, copying only the main database file while it is being written can miss relevant state in the journal files. Use an appropriate SQLite backup mechanism and test the result. This demonstration is not instructions to copy a running production file directly.
What this does not prove
We did not test writes occurring concurrently with the backup, interruption halfway through, disk failure, remote storage, encryption keys, a large database or the recovery of a real application. Those are separate experiments. A verified synthetic restore is a useful beginning, not a complete disaster-recovery plan.