Destructive protection
Blocked operations
Section titled “Blocked operations”These operations are blocked by default and require --allow-destructive:
drop_table— dropping entire tablesdrop_column— dropping columnsdrop_index— dropping indexesdrop_foreign_key— dropping foreign key constraintsdrop_check— dropping check constraintsdrop_unique_constraint— dropping unique constraintsdrop_view— dropping viewsdrop_materialized_view— dropping materialized viewsdrop_extension— dropping extensionsdisable_rls— disabling row-level securitydrop_policy— dropping RLS policiesdrop_trigger— dropping triggers- Column type narrowing (e.g.,
text->varchar(50)) - Enum value removal (
remove_enum_value)
Behavior
Section titled “Behavior”When a blocked operation is encountered:
- It is reported as “blocked” in the plan output
- The rest of the migration proceeds normally
- No data is lost
# See what would be blockednpx @smplcty/schema-flow plan
# Allow destructive operationsnpx @smplcty/schema-flow run --allow-destructiveAdvisory locking
Section titled “Advisory locking”Before running migrations, schema-flow acquires a PostgreSQL advisory lock. This prevents concurrent migration processes from conflicting. The lock is released after migration completes or on error.
Transactional execution
Section titled “Transactional execution”DDL runs within transactions. If any statement fails, the entire transaction rolls back. No partial migrations.
Timeouts
Section titled “Timeouts”| Setting | Default | Purpose |
|---|---|---|
| Lock timeout | 5000ms | Prevents blocking other queries while waiting for table locks |
| Statement timeout | 30000ms | Prevents long-running DDL from holding locks indefinitely |
Automatic retry
Section titled “Automatic retry”Transient errors are retried up to 3 times with exponential backoff:
| Error code | Meaning |
|---|---|
55P03 | Lock timeout |
57014 | Statement timeout / query cancellation |
40001 | Serialization failure |
40P01 | Deadlock detected |
Interrupted migrations
Section titled “Interrupted migrations”If a migration is interrupted:
- Re-running picks up where it left off (file hash tracking)
- Transactional phases either fully commit or fully roll back
- Failed
CONCURRENTLYoperations leave invalid indexes that can be detected and retried