Example: Risky Change with Explicit Constraints
This example shows how explicit constraints protect a system during a risky database schema change.
Context
Need to enforce uniqueness constraint on identifier field across entities, where data currently exists in JSONB with potential duplicates.
Intent
Goal: Guarantee one identifier belongs to exactly one entity, regardless of storage location.
Not goal: Rewrite entire entity management system.
Why now: Data inconsistencies causing reconciliation issues.
Trade-off: Temporary complexity during migration (two sources of truth).
Constraints
- Uniqueness: One identifier cannot belong to multiple entities
- Non-reuse: Soft-deleted entities do not free identifier for reuse
- Compatibility: Existing metadata format must continue working
- Low-risk rollout: Small dataset, rare updates → safe migration
Proposed Solution
Create separate normalized table with PRIMARY KEY on identifier:
- Database-level uniqueness enforcement
- Normalized structure
- Backward compatible with existing metadata
Risk Model
Risks:
1. Existing data collisions → migration fails
2. Concurrent updates → race conditions
3. Data inconsistency → dependent systems fail
Mitigation:
- Preflight audit to find collisions
- PRIMARY KEY prevents races
- Gradual migration with validation
Execution Plan
- Preflight audit (find collisions)
- Create table + backfill
- Add API for direct management
- Migrate consumers gradually
- Observe for 2+ weeks
- Clean up legacy data (optional)
Kill Criteria
- Data loss detected → rollback immediately
- Dependent systems fail to find entities → stop, investigate
- Collision rate > threshold → reassess approach
Outcome
- Uniqueness enforced at database level
- No production incidents
- Dependent systems migrated successfully
- System more maintainable