-
Notifications
You must be signed in to change notification settings - Fork 0
Risk Assessment
Vivek edited this page Jul 14, 2026
·
2 revisions
The engine classifies every schema change into one of 5 risk levels.
| Level | Color | Examples | Default Action |
|---|---|---|---|
none |
🟢 Green | CREATE TABLE, ADD nullable column | ✅ Allow |
low |
🔵 Blue | ADD COLUMN with default, CREATE INDEX | ✅ Allow |
medium |
🟡 Yellow | ALTER COLUMN type (widening), ADD FK | ✅ Allow |
high |
🟠 Orange | DROP INDEX, ALTER type (narrowing) | ❌ Block |
critical |
🔴 Red | DROP TABLE, DROP COLUMN, DROP SCHEMA | ❌ Block |
Zero risk. Safe operations that cannot cause data loss or downtime.
| Operation | Risk | Why |
|---|---|---|
| CREATE TABLE | none | New object, no existing data affected |
| ADD nullable column | none | No constraint violations |
| ADD CHECK constraint (NOT VALID) | none | Doesn't validate existing data |
| CREATE SEQUENCE | none | Independent object |
| CREATE TYPE | none | Type definitions don't affect data |
Minimal risk. Operations that may have minor performance impact.
| Operation | Risk | Why |
|---|---|---|
| ADD COLUMN with DEFAULT | low | Metadata change + single write |
| CREATE INDEX (non-concurrent) | low | Brief write lock on table |
| ADD NOT NULL (with safe pattern) | low | 3-step safe execution |
| ALTER COLUMN SET DEFAULT | low | Metadata-only change |
- Brief lock (milliseconds)
- No data movement
- Can run during normal operations
Moderate risk. Operations requiring careful planning.
| Operation | Risk | Why |
|---|---|---|
| ALTER COLUMN type (widening) | medium | Requires table rewrite for some types |
| ADD FK constraint (validated) | medium | Validates all rows |
| ALTER COLUMN type (same category) | medium | int → bigint OK, int → text needs cast |
| ADD UNIQUE constraint | medium | Requires index, validates data |
- Longer locks (seconds)
- May require table scan
- Plan for low-traffic periods
// Engine automatically uses safe patterns
ALTER COLUMN int_col TYPE bigint; // Widening: OK
ALTER COLUMN int_col TYPE varchar; // Type change: needs USINGHigh risk. Operations that can cause downtime or require careful rollback.
| Operation | Risk | Why |
|---|---|---|
| DROP INDEX | high | May affect query performance |
| ALTER COLUMN type (narrowing) | high | varchar(100) → varchar(50) truncates data |
| ADD NOT NULL (without safe pattern) | high | Fails if NULL exists |
| DROP CONSTRAINT | high | May affect data integrity |
| ALTER COLUMN DROP DEFAULT | high | Application might depend on it |
const plan = engine.plan(diff);
// High-risk changes block by default
plan.blocked === true;
// Override (dangerous)
await engine.migrate(pool, desired, {
riskThreshold: 'high' // Allow high-risk
});Before applying high-risk changes:
- Check application dependencies
- Verify no data truncation
- Test in staging
- Plan rollback
Critical risk. Destructive operations that cause data loss.
| Operation | Risk | Why |
|---|---|---|
| DROP TABLE | critical | permanently deletes all data |
| DROP COLUMN | critical | permanently deletes column data |
| DROP SCHEMA | critical | Deletes entire schema and all objects |
| DROP DATABASE | critical | Complete destruction |
| TRUNCATE TABLE | critical | Removes all rows without logging |
| ALTER COLUMN type (lossy) | critical | text → int loses data |
| DROP TYPE (in use) | critical | Breaks dependent objects |
Always blocked. Cannot be overridden without force: true.
await engine.migrate(pool, desired, {
force: true, // Required for critical
confirmDestructive: (changes) => {
console.log('These will be destroyed:', changes);
return true; // Must explicitly confirm
}
});diff.changes.forEach(change => {
if (change.objectKey === 'public.temp_table') {
change.risk = 'none'; // Override risk for specific change
}
});const engine = new PgMigrationEngine({
riskThreshold: 'medium' // Block medium and above
});await engine.migrate(pool, desired, {
force: true // Bypass all risk checks (dangerous)
});The engine evaluates risk based on:
- Operation type: CREATE < ALTER < DROP
- Object type: sequence < table < schema
- Data impact: none < metadata < data
- Reversibility: reversible < irreversible
- Dependency check: no dependents < has dependents
// Example: Risk calculation for ALTER COLUMN
const risk = assessRisk({
operation: 'ALTER_COLUMN',
fromType: 'varchar(100)',
toType: 'varchar(50)',
tableSize: 'large',
hasData: true
});
// Result: 'critical' (data truncation risk)| Risk Level | Default | Configurable |
|---|---|---|
| none | Allow | No (always allow) |
| low | Allow | No |
| medium | Allow | Yes (can block) |
| high | Block | Yes |
| critical | Block | No (requires force) |
- Safe-Migration-Patterns — How safe patterns reduce risk
- API-Reference — riskThreshold configuration