For a file-backed SQLite store use native maintenance to capture committed WAL contents.
Do not copy a live database with cp or open it through a separately bundled SQLite library
inside the engine process. PostgreSQL needs its own database/secret recovery procedure.
Take a consistent backup
The Node maintenance API is commerce.maintenance.backupTo(path) (alias backup). It uses
SQLite VACUUM INTO and writes an adjacent manifest with checksum, schema/migration metadata,
engine version and size. Check maintenance.isSupported() first and retain both files.
Use immutable operator-owned storage. A file and checksum are not a tested recovery plan.
Restore into a new path
The native layer verifies staged bytes, integrity, actual schema and manifest before
publication. Existing files, including empty placeholders, require explicit native overwrite;
symlinks and WAL/SHM/journal entries are refused. Never overwrite a database still open by
any process, or delete active journals to force recovery.
DatabaseManager from @stateset/cli provides asynchronous backup() and restore().
Await both. Manager restore requires a new path, always checks checksum/schema, and publishes
through a hard link that cannot replace another file. Its filesystem must support hard links.
It does not stop external writers or switch traffic for you.
Verify and cut over
- Stop writers and preserve the original database plus sidecars for investigation.
- Restore to a new controlled path with checksum verification and newer-schema rejection.
- Open a new engine; require integrity check
ok and verify schema/migration metadata.
- Check representative orders, stock, payments/returns, pending work, events and receipt tail.
- Test read-only access, then one writer, before progressively switching traffic.
Built-in migrations are forward-only. Reversing an engine upgrade means restoring a verified
compatible pre-upgrade snapshot; application migrations with explicit down SQL are a separate
registry. A rollback after new writes can discard business state.
Choose durability explicitly
SQLite uses WAL and defaults to synchronous=NORMAL. Set
STATESET_SQLITE_SYNCHRONOUS=FULL before opening the engine for commit-time synchronization
across pooled connections. Invalid settings, including OFF, fail. FULL still depends on the
filesystem/device honoring sync; it is not a host power-loss certification. Shutdown reports
blocked WAL checkpoints: close competing readers/writers and retry.
Retained source drills cover process termination before commit and after commit/before response,
same-key contention, bounded storage exhaustion, restore and receipt reconciliation. Those
are scoped tests, not measured production RPO/RTO, sustained soak, or host power-loss evidence.
Export is a different operation
Native maintenance also offers versioned JSON export/import. Coverage is domain-specific;
imports remap identities and cannot reconstruct every state-machine history from a create.
Use snapshots for identity-preserving disaster recovery. Inspect the installed export/import
contract before treating a round trip as a full backup.
See HTTP receipt recovery for unresolved requests,
and governed replay for durable command receipts. Last modified on October 20, 2026