
Database Design
- 527 installs
- 30.1k repo stars
- Updated August 4, 2026
- davila7/claude-code-templates
database-design is a Claude Code skill that generates production-ready database schemas, relationships, indexes, and migration plans from natural language requirements for developers who need structured SQL or NoSQL data
About
database-design is a Claude Code skill from davila7/claude-code-templates that turns natural language product requirements into production-oriented database artifacts. The skill produces entity-relationship structures, foreign-key relationships, index recommendations, and step-by-step migration plans suitable for PostgreSQL, MySQL, and similar relational stacks. Developers reach for database-design when bootstrapping a new service, refactoring a monolith schema, or translating PRD tables and workflows into normalized tables before writing ORM models or raw SQL migrations. With 508 installs on skills.sh, it fits early backend sprints where schema mistakes are expensive to unwind later.
- Converts product requirements into normalized relational or NoSQL schemas
- Outputs complete DDL, migration files, seed data, and query examples
- Includes indexing strategy, constraints, and performance recommendations
- Produces entity-relationship diagrams in Mermaid format
- Delivers ready-to-apply artifacts that feed directly into your ORM or query layer
Database Design by the numbers
- 527 all-time installs (skills.sh)
- Ranked #119 of 911 Databases skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/davila7/claude-code-templates --skill database-designAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 527 |
|---|---|
| repo stars | ★ 30.1k |
| Last updated | August 4, 2026 |
| Repository | davila7/claude-code-templates ↗ |
How do you design a production database schema from requirements?
Generate production-ready database schemas, relationships, indexes, and migration plans from natural language requirements.
Who is it for?
Backend engineers starting a new feature or service who need normalized schemas and migration steps before writing ORM code.
Skip if: Teams that already have finalized schemas and only need query tuning or DBA-level performance audits.
When should I use this skill?
A developer describes data entities, relationships, or storage needs and asks for schema, ERD, or migration output.
What you get
Entity-relationship schema, relationship map, index recommendations, and migration plan documents.
- ER schema
- migration plan
- index recommendations
By the numbers
- 508 installs on skills.sh
- Generates schemas, relationships, indexes, and migration plans as bundled outputs
Files
Database Design
Learn to THINK, not copy SQL patterns.
🎯 Selective Reading Rule
Read ONLY files relevant to the request! Check the content map, find what you need.
| File | Description | When to Read |
|---|---|---|
database-selection.md | PostgreSQL vs Neon vs Turso vs SQLite | Choosing database |
orm-selection.md | Drizzle vs Prisma vs Kysely | Choosing ORM |
schema-design.md | Normalization, PKs, relationships | Designing schema |
indexing.md | Index types, composite indexes | Performance tuning |
optimization.md | N+1, EXPLAIN ANALYZE | Query optimization |
migrations.md | Safe migrations, serverless DBs | Schema changes |
---
⚠️ Core Principle
- ASK user for database preferences when unclear
- Choose database/ORM based on CONTEXT
- Don't default to PostgreSQL for everything
---
Decision Checklist
Before designing schema:
- [ ] Asked user about database preference?
- [ ] Chosen database for THIS context?
- [ ] Considered deployment environment?
- [ ] Planned index strategy?
- [ ] Defined relationship types?
---
Anti-Patterns
❌ Default to PostgreSQL for simple apps (SQLite may suffice) ❌ Skip indexing ❌ Use SELECT * in production ❌ Store JSON when structured data is better ❌ Ignore N+1 queries
Database Selection (2025)
Choose database based on context, not default.
Decision Tree
What are your requirements?
│
├── Full relational features needed
│ ├── Self-hosted → PostgreSQL
│ └── Serverless → Neon, Supabase
│
├── Edge deployment / Ultra-low latency
│ └── Turso (edge SQLite)
│
├── AI / Vector search
│ └── PostgreSQL + pgvector
│
├── Simple / Embedded / Local
│ └── SQLite
│
└── Global distribution
└── PlanetScale, CockroachDB, TursoComparison
| Database | Best For | Trade-offs |
|---|---|---|
| PostgreSQL | Full features, complex queries | Needs hosting |
| Neon | Serverless PG, branching | PG complexity |
| Turso | Edge, low latency | SQLite limitations |
| SQLite | Simple, embedded, local | Single-writer |
| PlanetScale | MySQL, global scale | No foreign keys |
Questions to Ask
1. What's the deployment environment? 2. How complex are the queries? 3. Is edge/serverless important? 4. Vector search needed? 5. Global distribution required?
Indexing Principles
When and how to create indexes effectively.
When to Create Indexes
Index these:
├── Columns in WHERE clauses
├── Columns in JOIN conditions
├── Columns in ORDER BY
├── Foreign key columns
└── Unique constraints
Don't over-index:
├── Write-heavy tables (slower inserts)
├── Low-cardinality columns
├── Columns rarely queriedIndex Type Selection
| Type | Use For |
|---|---|
| B-tree | General purpose, equality & range |
| Hash | Equality only, faster |
| GIN | JSONB, arrays, full-text |
| GiST | Geometric, range types |
| HNSW/IVFFlat | Vector similarity (pgvector) |
Composite Index Principles
Order matters for composite indexes:
├── Equality columns first
├── Range columns last
├── Most selective first
└── Match query patternMigration Principles
Safe migration strategy for zero-downtime changes.
Safe Migration Strategy
For zero-downtime changes:
│
├── Adding column
│ └── Add as nullable → backfill → add NOT NULL
│
├── Removing column
│ └── Stop using → deploy → remove column
│
├── Adding index
│ └── CREATE INDEX CONCURRENTLY (non-blocking)
│
└── Renaming column
└── Add new → migrate data → deploy → drop oldMigration Philosophy
- Never make breaking changes in one step
- Test migrations on data copy first
- Have rollback plan
- Run in transaction when possible
Serverless Databases
Neon (Serverless PostgreSQL)
| Feature | Benefit |
|---|---|
| Scale to zero | Cost savings |
| Instant branching | Dev/preview |
| Full PostgreSQL | Compatibility |
| Autoscaling | Traffic handling |
Turso (Edge SQLite)
| Feature | Benefit |
|---|---|
| Edge locations | Ultra-low latency |
| SQLite compatible | Simple |
| Generous free tier | Cost |
| Global distribution | Performance |
Query Optimization
N+1 problem, EXPLAIN ANALYZE, optimization priorities.
N+1 Problem
What is N+1?
├── 1 query to get parent records
├── N queries to get related records
└── Very slow!
Solutions:
├── JOIN → Single query with all data
├── Eager loading → ORM handles JOIN
├── DataLoader → Batch and cache (GraphQL)
└── Subquery → Fetch related in one queryQuery Analysis Mindset
Before optimizing:
├── EXPLAIN ANALYZE the query
├── Look for Seq Scan (full table scan)
├── Check actual vs estimated rows
└── Identify missing indexesOptimization Priorities
1. Add missing indexes (most common issue) 2. Select only needed columns (not SELECT ) 3. Use proper JOINs (avoid subqueries when possible) 4. Limit early (pagination at database level) 5. Cache* (when appropriate)
ORM Selection (2025)
Choose ORM based on deployment and DX needs.
Decision Tree
What's the context?
│
├── Edge deployment / Bundle size matters
│ └── Drizzle (smallest, SQL-like)
│
├── Best DX / Schema-first
│ └── Prisma (migrations, studio)
│
├── Maximum control
│ └── Raw SQL with query builder
│
└── Python ecosystem
└── SQLAlchemy 2.0 (async support)Comparison
| ORM | Best For | Trade-offs |
|---|---|---|
| Drizzle | Edge, TypeScript | Newer, less examples |
| Prisma | DX, schema management | Heavier, not edge-ready |
| Kysely | Type-safe SQL builder | Manual migrations |
| Raw SQL | Complex queries, control | Manual type safety |
Schema Design Principles
Normalization, primary keys, timestamps, relationships.
Normalization Decision
When to normalize (separate tables):
├── Data is repeated across rows
├── Updates would need multiple changes
├── Relationships are clear
└── Query patterns benefit
When to denormalize (embed/duplicate):
├── Read performance critical
├── Data rarely changes
├── Always fetched together
└── Simpler queries neededPrimary Key Selection
| Type | Use When |
|---|---|
| UUID | Distributed systems, security |
| ULID | UUID + sortable by time |
| Auto-increment | Simple apps, single database |
| Natural key | Rarely (business meaning) |
Timestamp Strategy
For every table:
├── created_at → When created
├── updated_at → Last modified
└── deleted_at → Soft delete (if needed)
Use TIMESTAMPTZ (with timezone) not TIMESTAMPRelationship Types
| Type | When | Implementation |
|---|---|---|
| One-to-One | Extension data | Separate table with FK |
| One-to-Many | Parent-children | FK on child table |
| Many-to-Many | Both sides have many | Junction table |
Foreign Key ON DELETE
├── CASCADE → Delete children with parent
├── SET NULL → Children become orphans
├── RESTRICT → Prevent delete if children exist
└── SET DEFAULT → Children get default value#!/usr/bin/env python3
"""
Schema Validator - Database schema validation
Validates Prisma schemas and checks for common issues.
Usage:
python schema_validator.py <project_path>
Checks:
- Prisma schema syntax
- Missing relations
- Index recommendations
- Naming conventions
"""
import sys
import json
import re
from pathlib import Path
from datetime import datetime
# Fix Windows console encoding
try:
sys.stdout.reconfigure(encoding='utf-8', errors='replace')
except:
pass
def find_schema_files(project_path: Path) -> list:
"""Find database schema files."""
schemas = []
# Prisma schema
prisma_files = list(project_path.glob('**/prisma/schema.prisma'))
schemas.extend([('prisma', f) for f in prisma_files])
# Drizzle schema files
drizzle_files = list(project_path.glob('**/drizzle/*.ts'))
drizzle_files.extend(project_path.glob('**/schema/*.ts'))
for f in drizzle_files:
if 'schema' in f.name.lower() or 'table' in f.name.lower():
schemas.append(('drizzle', f))
return schemas[:10] # Limit
def validate_prisma_schema(file_path: Path) -> list:
"""Validate Prisma schema file."""
issues = []
try:
content = file_path.read_text(encoding='utf-8', errors='ignore')
# Find all models
models = re.findall(r'model\s+(\w+)\s*{([^}]+)}', content, re.DOTALL)
for model_name, model_body in models:
# Check naming convention (PascalCase)
if not model_name[0].isupper():
issues.append(f"Model '{model_name}' should be PascalCase")
# Check for id field
if '@id' not in model_body and 'id' not in model_body.lower():
issues.append(f"Model '{model_name}' might be missing @id field")
# Check for createdAt/updatedAt
if 'createdAt' not in model_body and 'created_at' not in model_body:
issues.append(f"Model '{model_name}' missing createdAt field (recommended)")
# Check for @relation without fields
relations = re.findall(r'@relation\([^)]*\)', model_body)
for rel in relations:
if 'fields:' not in rel and 'references:' not in rel:
pass # Implicit relation, ok
# Check for @@index suggestions
foreign_keys = re.findall(r'(\w+Id)\s+\w+', model_body)
for fk in foreign_keys:
if f'@@index([{fk}])' not in content and f'@@index(["{fk}"])' not in content:
issues.append(f"Consider adding @@index([{fk}]) for better query performance in {model_name}")
# Check for enum definitions
enums = re.findall(r'enum\s+(\w+)\s*{', content)
for enum_name in enums:
if not enum_name[0].isupper():
issues.append(f"Enum '{enum_name}' should be PascalCase")
except Exception as e:
issues.append(f"Error reading schema: {str(e)[:50]}")
return issues
def main():
project_path = Path(sys.argv[1] if len(sys.argv) > 1 else ".").resolve()
print(f"\n{'='*60}")
print(f"[SCHEMA VALIDATOR] Database Schema Validation")
print(f"{'='*60}")
print(f"Project: {project_path}")
print(f"Time: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
print("-"*60)
# Find schema files
schemas = find_schema_files(project_path)
print(f"Found {len(schemas)} schema files")
if not schemas:
output = {
"script": "schema_validator",
"project": str(project_path),
"schemas_checked": 0,
"issues_found": 0,
"passed": True,
"message": "No schema files found"
}
print(json.dumps(output, indent=2))
sys.exit(0)
# Validate each schema
all_issues = []
for schema_type, file_path in schemas:
print(f"\nValidating: {file_path.name} ({schema_type})")
if schema_type == 'prisma':
issues = validate_prisma_schema(file_path)
else:
issues = [] # Drizzle validation could be added
if issues:
all_issues.append({
"file": str(file_path.name),
"type": schema_type,
"issues": issues
})
# Summary
print("\n" + "="*60)
print("SCHEMA ISSUES")
print("="*60)
if all_issues:
for item in all_issues:
print(f"\n{item['file']} ({item['type']}):")
for issue in item["issues"][:5]: # Limit per file
print(f" - {issue}")
if len(item["issues"]) > 5:
print(f" ... and {len(item['issues']) - 5} more issues")
else:
print("No schema issues found!")
total_issues = sum(len(item["issues"]) for item in all_issues)
# Schema issues are warnings, not failures
passed = True
output = {
"script": "schema_validator",
"project": str(project_path),
"schemas_checked": len(schemas),
"issues_found": total_issues,
"passed": passed,
"issues": all_issues
}
print("\n" + json.dumps(output, indent=2))
sys.exit(0)
if __name__ == "__main__":
main()
Related skills
Forks & variants (1)
Database Design has 1 known copy in the catalog totaling 3 installs. They canonicalize to this original listing.
- xenitv1 - 3 installs
How it compares
Choose database-design when requirements exist but no schema yet; use query-optimization skills after tables are live.
FAQ
What does database-design output?
database-design outputs production-ready database schemas with entity relationships, recommended indexes, and a migration plan derived from natural language requirements, giving developers artifacts ready for ORM models or SQL migration files.
When should developers use database-design?
Developers should use database-design at the start of a backend build when tables, keys, and migrations are undefined. The skill converts feature requirements into normalized schemas before application code is written.