Database design
A skill library for AI coding agents with a CI quality gate: 38 skills, four-target sync, and an 18-check eval harness that fails the build on malformed skills.
npx -y skills add VJDiPaola/skill-forge --skill database-designAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
3 things to look at
- 11 days oldThe repository was created 11 days ago. New is not bad, but a brand new repository carrying a familiar-sounding name is the shape a typosquat arrives in, and there has been no time for anyone else to find a problem with it.
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Design database schemas, write and review SQL, plan migrations, and diagnose slow queries. Use when the user asks to model a domain in tables, add or change a schema, write a migration, pick indexes, review a query for performance, or choose between SQL and other storage. Trigger on schema design, migration, index, N+1, EXPLAIN, foreign key, or normalize.
SKILL.md
4.1 KB, as published. Nobody here has run it
Database Design
Schema design, SQL review, migrations, and query performance. Applies to Postgres, MySQL, and SQLite; call out dialect differences when they matter.
Not in scope
ORM-specific API questions (look up the ORM's docs), NoSQL data modeling, data warehousing/analytics pipeline design, and DBA operations (replication, backups, tuning server config). For app-level security review of queries, see the security skills.
Schema design ground rules
- Start from the queries, not the entities. List the top 5 reads and writes the app will do, then shape tables so those are cheap.
- Normalize until it hurts, denormalize where a measured read pattern justifies it. Record the justification in a comment or migration note.
- Every table gets: a primary key (prefer surrogate
idunless a natural key is truly stable),created_at, andupdated_atwhere rows mutate. - Foreign keys ON by default. If someone wants them off for "performance," ask for the benchmark.
- Prefer
text+ check constraints over enums in Postgres when values will change; enums need a migration per value. - Timestamps in UTC (
timestamptzin Postgres). Convert at the edge. - Money as integer cents or
numeric, never float. - Soft deletes (
deleted_at) only when the product needs undo or audit; they complicate every query and unique constraint. Partial unique indexes (WHERE deleted_at IS NULL) fix the constraint side.
Migration rules
- Migrations are append-only and each one must be runnable against production data, not just an empty dev database.
- Split risky changes into deploy-safe steps: add nullable column, backfill in batches, add constraint
NOT VALIDthenVALIDATE, then flip application code. NeverALTER TABLE ... SET NOT NULLon a large hot table in one step. - Adding an index on a big table:
CREATE INDEX CONCURRENTLY(Postgres) outside a transaction. - Renames are two migrations plus an app deploy in between (add new, dual-write or view, drop old). A bare
RENAME COLUMNbreaks the running old code during deploy. - Every migration states its rollback. If it's irreversible (dropped data), say so loudly in the file.
Query review checklist
- Run
EXPLAIN (ANALYZE, BUFFERS)(Postgres) orEXPLAIN(MySQL) before guessing. - Seq scan on a large table filtered by a selective column: missing or unusable index. Check for functions on the indexed column (
WHERE lower(email) = ...needs an expression index). - N+1: loops issuing one query per row. Fix with a join,
INlist, or the ORM's eager loading. OFFSETpagination degrades linearly; use keyset pagination (WHERE (created_at, id) < (?, ?) ORDER BY ... LIMIT ?) for deep pages.SELECT *in application code hides schema coupling and bloats the wire; select the columns used.- Watch for implicit type casts killing index use (text column compared to integer).
- Composite index column order: equality columns first, then the range/sort column. An index on
(a, b)servesWHERE a = ?but notWHERE b = ?.
Index heuristics
- Index foreign key columns; most databases don't do it automatically and unindexed FKs make deletes on the parent table slow.
- One composite index that serves several queries beats three overlapping single-column indexes.
- Don't index low-cardinality columns alone (booleans, small enums) unless combined into a composite or partial index.
- Each index taxes every write. On write-heavy tables, justify each one with a query it serves.
When asked "SQL or something else"
Default to Postgres unless there's a concrete reason not to. Redis for caches and queues alongside it, not instead of it. Reach for a document store only when the data is truly schemaless AND query patterns are key-based. "We might need to scale" is not a reason; "we measured and write volume exceeds X" is.