schema-iteration
$npx skills add blunotech-dev/agents --skill schema-iterationRefactors messy or MVP-stage database schemas into clean, production-ready structures by normalizing relations, removing redundancy, adding indexes, and generating safe migration SQL or ORM migrations without data loss. Trigger for any schema cleanup, database refactoring, normalization, indexing, migration, or data model improvement request, including Prisma schema optimization and relation analysis.
References
| name | description | category |
|---|---|---|
| schema-iteration | Refactors messy or MVP-stage database schemas into clean, production-ready structures by normalizing relations, removing redundancy, adding indexes, and generating safe migration SQL or ORM migrations without data loss. Trigger for any schema cleanup, database refactoring, normalization, indexing, migration, or data model improvement request, including Prisma schema optimization and relation analysis. | Rapid Mvp Building |
Schema Iteration
Analyzes a database schema for structural problems, produces a refactored version, and generates a safe migration that preserves all existing data.
Workflow
1. Ingest the Schema
Accept input in any form:
- Prisma schema (
.prisma) - Raw SQL (
CREATE TABLEstatements) - ORM model definitions (SQLAlchemy, Django, ActiveRecord, TypeORM)
- A prose description of the current tables and fields
If the schema is missing, ask for it. If only a prose description is given, reconstruct a working schema from it before analyzing.
Also clarify (if not obvious):
- Database engine (PostgreSQL, MySQL, SQLite, etc.)
- ORM in use (Prisma, Drizzle, SQLAlchemy, etc.) — determines migration output format
- Approximate data volume — affects index strategy and migration approach
- Any known pain points the user has already noticed
2. Audit the Schema
Work through each category. Flag every issue found with a short label so the user can follow along.
Normalization
- Repeated columns that belong in a separate table (1NF/2NF/3NF violations)
- Many-to-many relations stored as comma-separated strings or JSON arrays instead of a join table
- Denormalized fields that create update anomalies (e.g. storing
user_emailon everyOrderrow)
Relation integrity
- Missing foreign key constraints
- Nullable foreign keys that should be non-nullable (or vice versa)
- Cascade behavior not set where it should be (
ON DELETE CASCADEvsSET NULLvsRESTRICT) - Circular or ambiguous relations
Indexes
- Missing index on every foreign key column (the most common oversight)
- Missing index on columns used in frequent
WHERE,ORDER BY, orJOINclauses - Redundant indexes (e.g. an index on
(a, b)makes a standalone index on(a)redundant) - Unique constraints missing on columns that must be unique
Naming and conventions
- Inconsistent casing (
userIdvsuser_idin the same schema) - Ambiguous column names (
data,info,value,flag) - Table names that mix singular/plural
Types
- Using
TEXTwhere a constrainedVARCHARorENUMwould enforce correctness - Using
INTfor IDs on a table that will grow large (considerBIGINT) - Storing money as
FLOATinstead ofDECIMAL/NUMERIC - Storing datetimes as strings instead of proper timestamp types
3. Produce the Refactored Schema
Output the full cleaned schema — not just the diffs. Include:
- All original tables (with fixes applied)
- Any new tables introduced (e.g. join tables, lookup tables)
- All foreign keys with explicit cascade behavior
- All indexes (both those that existed and new ones added)
- Inline comments explaining non-obvious decisions
For Prisma: output a valid .prisma schema block.
For SQL: output complete CREATE TABLE statements.
For ORM models: match the user's existing ORM style.
4. Generate the Migration
This is the most safety-critical part. Every step must be reversible or at least non-destructive.
Golden rules:
- Never
DROP COLUMNorDROP TABLEin the same transaction as data is being moved — always move first, verify, then drop in a separate step (or leave the drop for the user to run after they confirm) - Never rename a column directly on a busy production table — add the new column, backfill, then drop the old one
- Add indexes
CONCURRENTLY(PostgreSQL) or withALGORITHM=INPLACE(MySQL) when possible to avoid table locks - Wrap DDL in a transaction where the engine supports transactional DDL (PostgreSQL yes, MySQL no — call this out)
Migration output structure:
-- ============================================================
-- Migration: <short description>
-- Generated by: schema-iteration skill
-- Safe to run on: <engine>
-- Transactional DDL: yes/no
-- ============================================================
-- STEP 1: Add new columns / tables (non-destructive)
...
-- STEP 2: Backfill data
...
-- STEP 3: Add constraints and indexes
...
-- STEP 4 (run after verifying data): Drop deprecated columns/tables
-- NOTE: Review before running. These statements are intentionally
-- separated so you can verify data integrity first.
...
For ORM migrations (Prisma, Alembic, etc.), output the migration file in the correct format for that tool. See references/orm-migrations.md for tool-specific patterns.
5. Summarize Changes
After the schema and migration, produce a concise change log:
CHANGES SUMMARY
───────────────
Normalized: [list tables/columns affected]
New tables: [list any added]
FKs added: [count and list]
Indexes added: [count and list]
Types fixed: [list]
Naming fixed: [list]
⚠ Breaking: [any changes that require app-layer updates]
Call out anything that requires a corresponding change in application code (e.g. a renamed column, a removed denormalized field now fetched via join).
6. Optional Follow-ups (offer after main output)
- Query audit: given sample queries from the user, verify they'll benefit from the new indexes
- Seed data update: update fixture/seed files to match the new schema
- ORM model update: update TypeScript types, Pydantic models, etc. to match
- Rollback migration: generate the inverse migration
Reference Files
references/orm-migrations.md— Prisma, Alembic, Drizzle, and ActiveRecord migration patternsreferences/index-strategy.md— When to add composite indexes, partial indexes, and covering indexes