ef-core-migration-safetylisted
Install: claude install-skill Sarmkadan/dotnet-senior-skills
# EF Core Migration Safety
## Classify every migration before merging
1. **Additive online** - new nullable column, new table, new index (if built concurrently). Safe to deploy in any order.
2. **Additive blocking** - new NOT NULL column without default on a large table, new index without `CONCURRENTLY` (Postgres) / `ONLINE = ON` (SQL Server). Locks the table for the duration.
3. **Destructive** - drop column/table, narrow a type, add a constraint existing rows violate, rename. Requires the expand/contract pattern below.
Grep the generated migration for `DropColumn`, `DropTable`, `AlterColumn`, `RenameColumn`, `AddColumn` with `nullable: false`. Any hit means the migration cannot be reviewed by skimming the model diff - read the SQL via `dotnet ef migrations script`.
## Renames are drops in disguise
EF cannot always tell a rename from drop+add. Verify the migration contains `RenameColumn`, not this:
```csharp
// WRONG: silently destroys data
migrationBuilder.DropColumn(name: "Surname", table: "Users");
migrationBuilder.AddColumn<string>(name: "LastName", table: "Users");
```
If the scaffolder produced drop+add, hand-edit it to `RenameColumn`. Test by applying to a database with data, not an empty one.
## Zero-downtime column changes (expand/contract)
Old app code and new schema coexist during a rolling deploy. Never ship a migration the *previous* app version cannot run against.
Adding a required column:
```csharp
// Release 1: add nullable, app writes it
migration