Schema evolution

Change schemas without guessing about data loss.

Trestle previews destructive effects and rebuilds collection metadata and its physical table inside one transaction. The rebuild strategy is provider-neutral: it creates a compatible temporary table with the new field DDL, copies preserved values, drops the old table and renames the temporary one; SQLite uses STRICT and typed checks, while PostgreSQL uses its native types. Both engines reject incompatible existing data in the same transaction, leaving the old metadata and rows intact.

Safe additive change

Adding an optional field, or a required field with a compatible default, preserves every existing record.

// Add an optional deadline
{"name":"due_at","type":"datetime","required":false}

Changes requiring acknowledgement

Removing a field, changing its type, or making it required returns 409 schema_acknowledgement_required. Repeat the reviewed request with:

X-Trestle-Acknowledge-Schema: true

Acknowledgement permits the attempt; it does not override physical constraints. Incompatible existing data still rejects the rebuild and leaves the old schema and rows intact.

Example migration strategy

  1. Add status_v2 as optional.
  2. Backfill it in bounded 1,000-record batches.
  3. Verify every record has a valid value.
  4. Change status_v2 to required and acknowledge the rebuild.
  5. Move clients to the new field.
  6. Remove the old status field in a later reviewed change.

Rebuild sequence

  1. Create a temporary strict table with the requested schema.
  2. Copy metadata columns and fields whose stable IDs remain.
  3. Let the database validate required, type, uniqueness and JSON constraints.
  4. Drop the old table and atomically rename the validated replacement.
  5. Commit metadata and physical schema together.

Back up before destructive changes

# Create and download a current backup from the Backups dashboard
# then run restore preflight before changing production schema.

Renaming a field while retaining its internal field ID preserves its column and data. Recreating a similarly named field is not the same operation.