/database
Reviews schema design, SQL queries, ORM patterns. Use when junior creates schema, writes queries, adds migrations, works with Prisma/MongoDB/PostgreSQL, or asks "is this SQL safe", "N+1", "index".
$ npx -y skills add DanielPodolsky/ownyourcode --skill database --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/database
Context preview
The summary Claude sees to decide when to auto-load this skill.
Reviews schema design, SQL queries, ORM patterns. Use when junior creates schema, writes queries, adds migrations, works with Prisma/MongoDB/PostgreSQL, or asks "is this SQL safe", "N+1", "index".
SKILL.md
database.SKILL.mdname: database-fundamentals
description: Reviews schema design, SQL queries, ORM patterns. Use when junior creates schema, writes queries, adds migrations, works with Prisma/MongoDB/PostgreSQL, or asks "is this SQL safe", "N+1", "index".
Database Fundamentals Review
> "Your database is the foundation. Build it wrong, and everything above it will crack."
When to Apply
Activate this skill when reviewing:
- Schema design and migrations
- SQL/NoSQL queries
- ORM model definitions
- Data relationships
- Index creation
- Query performance
---
Review Checklist
Schema Design
- [ ] **Normalization**: Is data normalized appropriately (no excessive duplication)?
- [ ] **Denormalization justified**: If denormalized, is there a performance reason?
- [ ] **Primary keys**: Does every table have a clear primary key?
- [ ] **Foreign keys**: Are relationships enforced at the database level?
- [ ] **Data types**: Are appropriate types used (not everything TEXT)?
Indexes
- [ ] **Query-based**: Are indexes created for frequently queried columns?
- [ ] **Composite indexes**: Are multi-column queries covered?
- [ ] **Not over-indexed**: Are there unnecessary indexes slowing writes?
- [ ] **Unique constraints**: Are unique fields enforced at DB level?
Queries
- [ ] **No N+1**: Are related records fetched in bulk?
- [ ] **Select specific fields**: Are we avoiding `SELECT *`?
- [ ] **Pagination**: Do list queries limit results?
- [ ] **Parameterized**: Are all queries parameterized (no string concatenation)?
Migrations
- [ ] **Reversible**: Can this migration be rolled back?
- [ ] **No data loss**: Will existing data survive the migration?
- [ ] **Tested**: Has this been tested against production-like data?
- [ ] **Incremental**: Are large changes broken into smaller migrations?
---
Common Mistakes (Anti-Patterns)
1. The N+1 Query Problem
❌ // 1 query for users + N queries for posts
const users = await User.findAll();
for (const user of users) {
user.posts = await Post.findAll({ where: { userId: user.id } });
}
✅ // 1 query with JOIN
const users = await User.findAll({
include: [{ model: Post }]
});
// Or 2 queries with IN clause
const users = await User.findAll();
const userIds = users.map(u => u.id);
const posts = await Post.findAll({ where: { userId: userIds } });2. Missing Indexes
❌ // Queried frequently, but no index
SELECT * FROM orders WHERE user_id = ?
SELECT * FROM products WHERE category = ? AND status = 'active'
✅ CREATE INDEX idx_orders_user_id ON orders(user_id);
CREATE INDEX idx_products_category_status ON products(category, status);
3. SELECT * Everywhere
❌ SELECT * FROM users; // Returns 50 columns
✅ SELECT id, name, email FROM users; // Only what's needed
4. String Concatenation (SQL Injection)
❌ db.query(`SELECT * FROM users WHERE email = '${email}'`);
✅ db.query('SELECT * FROM users WHERE email = ?', [email]);5. Destructive Migrations
❌ -- Can't be rolled back
DROP TABLE users;
ALTER TABLE orders DROP COLUMN status;
✅ -- Add new, migrate data, then drop old (in separate migrations)
-- Migration 1: Add new column
ALTER TABLE orders ADD COLUMN status_new VARCHAR(20);
-- Migration 2: Copy data
UPDATE orders SET status_new = status;
-- Migration 3: Drop old (after verification)
ALTER TABLE orders DROP COLUMN status;
---
Socratic Questions
Ask the junior these questions instead of giving answers:
1. **Schema**: "Why did you choose this data type?" 2. **Relationships**: "What happens if this related record is deleted?" 3. **Indexes**: "Which columns are queried together? Are they indexed?" 4. **N+1**: "How many queries does this operation execute?" 5. **Migration**: "What happens if we need to roll this back?"
---
Normalization Quick Reference
| Form | Rule | Example Issue | |------|------|---------------| | 1NF | No repeating groups | `tags: "js,react,node"` should be separate table | | 2NF | No partial dependencies | Order item price duplicated from products | | 3NF | No transitive dependencies | Storing city AND zip code (zip determines city) |
When to Denormalize
- Read-heavy workloads with rare writes
- Calculated aggregates (e.g., order totals)
- Caching frequently accessed derived data
---
Index Strategy
-- Single column (most common)
CREATE INDEX idx_users_email ON users(email);
-- Composite (for multi-column queries)
-- Order matters! Most selective first
CREATE INDEX idx_orders_user_date ON orders(user_id, created_at);
-- Partial (for filtered queries)
CREATE INDEX idx_active_users ON users(email) WHERE active = true;
-- Unique (enforces constraint)
CREATE UNIQUE INDEX idx_users_email_unique ON users(email);
Index Rules of Thumb
1. Index columns in WHERE clauses 2. Index columns in JOIN conditions 3. Index columns in ORDER BY (if used with WHERE) 4. Don't over-index write-heavy tables 5. Consider composite indexes for multi-column queries
---
Query Optimization Checklist
1. [ ] Use EXPLAIN to analyze query plan 2. [ ] Avoid SELECT * - specify columns 3. [ ] Use LIMIT for pagination 4. [ ] Add indexes for WHERE/JOIN columns 5. [ ] Use WHERE instead of HAVING when possible 6. [ ] Avoid functions on indexed columns in WHERE 7. [ ] Use EXISTS instead of IN for large subqueries
---
Red Flags to Call Out
| Flag | Question to Ask | |------|-----------------| | Query in a loop | "Can we fetch all this data in one query?" | | No pagination | "What if there are 1 million records?" | | SELECT * | "Do we need all 50 columns?" | | String in query | "Is this protected against SQL injection?" | | No indexes on foreign keys | "How fast are JOINs on this table?" | | DROP TABLE in migration | "How do we roll this back?" | | TEXT for everything | "Should this be an INT or DATE instead?" | | No foreign key constraints | "What prevents orphaned records?" |
---
##
Read more
name: database-fundamentals description: Reviews schema design, SQL queries, ORM patterns. Use when junior creates schema, writes queries, adds migrations, works with Prisma/MongoDB/PostgreSQL, or asks "is this SQL safe", "N+1", "index".
Database Fundamentals Review
> "Your database is the foundation. Build it wrong, and everything above it will crack."
When to Apply
Activate this skill when reviewing:
- Schema design and migrations
- SQL/NoSQL queries
- ORM model definitions
- Data relationships
- Index creation
- Query performance
---
Review Checklist
Schema Design
- [ ] **Normalization**: Is data normalized appropriately (no excessive duplication)?
- [ ] **Denormalization justified**: If denormalized, is there a performance reason?
- [ ] **Primary keys**: Does every table have a clear primary key?
- [ ] **Foreign keys**: Are relationships enforced at the database level?
- [ ] **Data types**: Are appropriate types used (not everything TEXT)?
Indexes
- [ ] **Query-based**: Are indexes created for frequently queried columns?
- [ ] **Composite indexes**: Are multi-column queries covered?
- [ ] **Not over-indexed**: Are there unnecessary indexes slowing writes?
- [ ] **Unique constraints**: Are unique fields enforced at DB level?
Queries
- [ ] **No N+1**: Are related records fetched in bulk?
- [ ] **Select specific fields**: Are we avoiding `SELECT *`?
- [ ] **Pagination**: Do list queries limit results?
- [ ] **Parameterized**: Are all queries parameterized (no string concatenation)?
Migrations
- [ ] **Reversible**: Can this migration be rolled back?
- [ ] **No data loss**: Will existing data survive the migration?
- [ ] **Tested**: Has this been tested against production-like data?
- [ ] **Incremental**: Are large changes broken into smaller migrations?
---
Common Mistakes (Anti-Patterns)
1. The N+1 Query Problem
❌ // 1 query for users + N queries for posts
const users = await User.findAll();
for (const user of users) {
user.posts = await Post.findAll({ where: { userId: user.id } });
}
✅ // 1 query with JOIN
const users = await User.findAll({
include: [{ model: Post }]
});
// Or 2 queries with IN clause
const users = await User.findAll();
const userIds = users.map(u => u.id);
const posts = await Post.findAll({ where: { userId: userIds } });2. Missing Indexes
❌ // Queried frequently, but no index SELECT * FROM orders WHERE user_id = ? SELECT * FROM products WHERE category = ? AND status = 'active' ✅ CREATE INDEX idx_orders_user_id ON orders(user_id); CREATE INDEX idx_products_category_status ON products(category, status);
3. SELECT * Everywhere
❌ SELECT * FROM users; // Returns 50 columns ✅ SELECT id, name, email FROM users; // Only what's needed
4. String Concatenation (SQL Injection)
❌ db.query(`SELECT * FROM users WHERE email = '${email}'`);
✅ db.query('SELECT * FROM users WHERE email = ?', [email]);5. Destructive Migrations
❌ -- Can't be rolled back DROP TABLE users; ALTER TABLE orders DROP COLUMN status; ✅ -- Add new, migrate data, then drop old (in separate migrations) -- Migration 1: Add new column ALTER TABLE orders ADD COLUMN status_new VARCHAR(20); -- Migration 2: Copy data UPDATE orders SET status_new = status; -- Migration 3: Drop old (after verification) ALTER TABLE orders DROP COLUMN status;
---
Socratic Questions
Ask the junior these questions instead of giving answers:
1. **Schema**: "Why did you choose this data type?" 2. **Relationships**: "What happens if this related record is deleted?" 3. **Indexes**: "Which columns are queried together? Are they indexed?" 4. **N+1**: "How many queries does this operation execute?" 5. **Migration**: "What happens if we need to roll this back?"
---
Normalization Quick Reference
| Form | Rule | Example Issue | |------|------|---------------| | 1NF | No repeating groups | `tags: "js,react,node"` should be separate table | | 2NF | No partial dependencies | Order item price duplicated from products | | 3NF | No transitive dependencies | Storing city AND zip code (zip determines city) |
When to Denormalize
- Read-heavy workloads with rare writes
- Calculated aggregates (e.g., order totals)
- Caching frequently accessed derived data
---
Index Strategy
-- Single column (most common) CREATE INDEX idx_users_email ON users(email); -- Composite (for multi-column queries) -- Order matters! Most selective first CREATE INDEX idx_orders_user_date ON orders(user_id, created_at); -- Partial (for filtered queries) CREATE INDEX idx_active_users ON users(email) WHERE active = true; -- Unique (enforces constraint) CREATE UNIQUE INDEX idx_users_email_unique ON users(email);
Index Rules of Thumb
1. Index columns in WHERE clauses 2. Index columns in JOIN conditions 3. Index columns in ORDER BY (if used with WHERE) 4. Don't over-index write-heavy tables 5. Consider composite indexes for multi-column queries
---
Query Optimization Checklist
1. [ ] Use EXPLAIN to analyze query plan 2. [ ] Avoid SELECT * - specify columns 3. [ ] Use LIMIT for pagination 4. [ ] Add indexes for WHERE/JOIN columns 5. [ ] Use WHERE instead of HAVING when possible 6. [ ] Avoid functions on indexed columns in WHERE 7. [ ] Use EXISTS instead of IN for large subqueries
---
Red Flags to Call Out
| Flag | Question to Ask | |------|-----------------| | Query in a loop | "Can we fetch all this data in one query?" | | No pagination | "What if there are 1 million records?" | | SELECT * | "Do we need all 50 columns?" | | String in query | "Is this protected against SQL injection?" | | No indexes on foreign keys | "How fast are JOINs on this table?" | | DROP TABLE in migration | "How do we roll this back?" | | TEXT for everything | "Should this be an INT or DATE instead?" | | No foreign key constraints | "What prevents orphaned records?" |
---
##
Claude Code workflow for AI-mentored development. Work efficiently with Spec-Driven Development and the 6 Gates. Built to fight cognitive offloading — for developers using AI to grow and maintain ownership.
Repo: DanielPodolsky/ownyourcode
Other skills on ownyourcode.
- /resume-bullets
Transforms completed work into powerful resume bullet points with action verbs, technical context, and quantified impact. Use when completing tasks, updating portfolio, or preparing job applications.
Open skill - /star-stories
Transforms completed work into STAR interview stories (Situation, Task, Action, Result). Use when completing tasks, preparing for behavioral interviews, or documenting achievements.
Open skill - /accessibility
Reviews accessibility including WCAG, ARIA, keyboard navigation. Use when junior builds forms, buttons, modals, interactive elements, or asks "is this accessible", "a11y", "screen reader".
Open skill - /backend
Reviews API design, REST conventions, and backend architecture. Use when junior builds API endpoints, Express routes, middleware, controllers, or asks "is this RESTful", "check my endpoint".
Open skill - /debugging
Guides systematic debugging through Protocol D (READ, ISOLATE, DOCS, HYPOTHESIZE, VERIFY). Use when junior says "stuck", "not working", "broken", "bug", "error", "crashed", "failing", "can't figure out", or expresses frustration. Do NOT use for general questions.
Open skill - /documentation
Guides documentation standards including READMEs, JSDoc, and code comments. Use when writing documentation, adding comments, or explaining code. Enforces "WHY not WHAT" principle.
Open skill

