Adding or changing a field normally requires updates to:
- The domain model and all constructors/usages
- The SeaORM entity in the domain object's
db.rs - A new migration under
src/leicmin/src/data/migrations/ - Queries, services, seeds, and tests that depend on the field
The entity and migration must agree on the field's PostgreSQL type, nullability, default, enum type, index, and constraints.
Adding a column safely
For an existing table, use an additive deployment sequence:
- Add the entity field as nullable, or add it with a safe constant default
- Deploy the migration and backfill existing rows when necessary
- Update application writes and reads to handle both old and new rows
- Verify the backfill and only then enforce
NOT NULLor remove a temporary default in a later migration
For large tables, consider lock duration and batch the backfill. Do not add a NOT NULL column without a default to a populated table.
Example for a constant default:
manager
.alter_table(
Table::alter()
.table(Widgets::Table)
.add_column_if_not_exists(
ColumnDef::new(Widgets::Enabled)
.boolean()
.not_null()
.default(false),
)
.to_owned(),
)
.await?;
Use add_column_if_not_exists only when accepting an already-present, compatible column is safe. It does not verify that an existing column has the correct definition.
Renaming, removing, or changing types
Do not combine a destructive rename or type change with an application release that still expects the old shape. Prefer a compatibility sequence:
- Add the replacement column or structure
- Backfill it from the old value
- Deploy code that reads/writes the compatible representation
- Remove the old column in a later migration after all callers are updated
Dropping or rewriting data requires an explicit data-loss review. Do not use a blind cast or overwrite existing values without checking the data first.
Enums and PostgreSQL-specific operations
Use guarded execute_unprepared SQL for PostgreSQL enum changes or other operations SeaORM cannot express. Check pg_enum before adding or renaming a value. PostgreSQL generally cannot remove enum values, so document the limitation and leave the value in place in down.