Schema design, normalization analysis, migration planning, and index strategy for relational and NoSQL databases.
"Your schema is your data contract with the future."
Invoked when designing a new database schema or modifying an existing one. Covers relational (PostgreSQL, MySQL) and document (MongoDB, DynamoDB) databases.
Steps:
Steps:
up and down scripts.Steps:
Steps:
| Field | Type | Description |
|---|---|---|
schema_ddl | string | CREATE TABLE statements |
migrations | string[] | Ordered migration files |
index_plan | object | Index recommendations with rationale |
er_diagram | string | Mermaid ER diagram |
data-access skill).db-tuning skill).api-contract-design skill).up and down scripts and be idempotent.{field} could belong to {table_a} or {table_b}. Which entity owns this data?"{data} inline denormalizes the schema. Should I extract it into a separate table with a foreign key, or keep it inline for read performance?"{column} from {table}. This is irreversible in production. Should I proceed, or use a soft-deprecation approach (rename + nullable)?"{entity_a} and {entity_b} — one-to-one, one-to-many, or many-to-many?"| Situation | Action |
|---|---|
| Greenfield schema with well-defined entities | Design in 3NF; generate CREATE TABLE DDL and an ER diagram |
| Read-heavy workload with complex joins | Consider targeted denormalization; document the trade-off in a migration comment and an ADR |
| Adding a column to a table with millions of rows | Recommend online DDL tool (pt-online-schema-change, pg_repack) and a phased migration |
| Multiple entities share identical fields (e.g., address) | Extract to a shared table with foreign keys unless performance benchmarks justify embedding |
| User wants to store hierarchical data (tree structures) | Evaluate adjacency list, nested set, materialized path, or closure table — recommend based on read/write ratio |
| Foreign key creates a circular dependency | Use nullable FK on one side and enforce integrity at the application level; document in an ADR |
| Query patterns are unknown or evolving | Start with minimal indexes (PK + FK); plan a review after real query data is available |
down scripts.| Failure | Symptom | Mitigation |
|---|---|---|
| Migration is not idempotent | Re-running the migration fails with "already exists" errors | Use IF NOT EXISTS / IF EXISTS guards in all DDL statements |
Missing down migration | Cannot roll back a failed deployment | Require both up and down scripts as part of the generation step; validate by running down then up in a test DB |
| Irreversible data loss from destructive DDL | Dropped column contained data not backed up elsewhere | Multi-step migration: rename column → deploy → verify → drop after grace period |
| Over-indexing on write-heavy tables | Insert/update latency increases significantly | Cap index count warnings at 5 per table; require performance justification for each additional index |
| Wrong cardinality assumption | Join table created for a one-to-many relationship, or FK placed incorrectly | Always confirm cardinality with the user before generating DDL when the domain model is ambiguous |
| Schema drift between environments | Dev and prod schemas diverge due to manual DDL changes | Track all schema changes exclusively through versioned migration files; never apply ad-hoc DDL |
[{timestamp}] SCHEMA_DESIGNED — Tables: [{table_names}] | Engine: {db_engine} | Normalization: {level}[{timestamp}] MIGRATION_GENERATED — File: {filename} | Direction: up+down | Changes: {summary}[{timestamp}] INDEX_ADDED — Table: {table} | Columns: [{columns}] | Type: {btree|gin|hash} | Rationale: "{reason}"[{timestamp}] DESTRUCTIVE_CHANGE_APPROVED — Table: {table} | Operation: {drop_column|drop_table|type_change} | User confirmed: yes[{timestamp}] ER_DIAGRAM_GENERATED — Format: Mermaid | Entities: {count} | File: {filename}[{timestamp}] SEED_DATA_GENERATED — Tables: [{table_names}] | Rows: {count} | Idempotent: yes