Database migrations
Numbered application migrations run before the service becomes ready and record their name and UTC application time.
Atomic upgrades
Each current migration executes in a transaction. A failed statement rolls the migration back, leaves the schema version unchanged, closes the database, and prevents the server from listening.
Version behavior
A fresh database applies every migration in order. Restarting an up-to-date database is a no-op. The applied version is derived from validated migration history; on SQLite, PRAGMA user_version is only a compatibility mirror that a valid history may restore. A database with a schema version newer than the executable, or with history that is missing, non-contiguous, misnamed or in disagreement with the marker, is rejected rather than guessed at.
Current schema
Trestle-owned tables store migration history, system metadata, identities, events, jobs, audit facts and integration state. Collection validation prevents user schemas from colliding with the reserved namespace.
CP22 provides checksum-verified binary update and rollback, while CP23 exercises every retained schema boundary and restore path. Back up first: executable rollback never promises an automatic database downgrade.
Offline cross-provider migration
An explicit offline trestle migrate command moves data between SQLite and the PostgreSQL provider using the portable logical format. It opens the source read-only, requires an empty destination, provider and schema preflight, a zero-write dry run, the explicit --confirm-migration flag, stable IDs, counts and a content checksum, and destination verification before cutover. Operator pg_dump and managed-service backup remain separate responsibilities.