
Database Design
- 1.8k installs
- 44k repo stars
- Updated July 27, 2026
- sickn33/antigravity-awesome-skills
database-design is an agent skill for "Database design principles and decision-making. Schema design, indexing strategy, ORM selection, serverless databases."
About
The database-design skill "Database design principles and decision-making. Schema design, indexing strategy, ORM selection, serverless databases." It covers aSK user for database preferences when unclear. Key workflows include choose database/ORM based on CONTEXT. This skill is applicable to execute the workflow or actions described in the overview. Developers invoke database-design when the task matches the triggers and reference files in SKILL.md for grounded, stepwise execution. Reference files and progressive disclosure keep context focused while preserving concrete commands, configuration fields, and validation checks copied from the upstream documentation. Reference files and progressive disclosure keep context focused while preserving concrete commands, configuration fields, and validation checks copied from the upstream documentation. Reference files and progressive disclosure keep context focused while preserving concrete commands, configuration fields, and validation checks copied from the upstream documentation.
- ASK user for database preferences when unclear
- Choose database/ORM based on CONTEXT
- Don't default to PostgreSQL for everything
- Asked user about database preference?
- Chosen database for THIS context?
Database Design by the numbers
- 1,803 all-time installs (skills.sh)
- +40 installs in the week ending Jul 28, 2026 (Skillselion tracking)
- Ranked #409 of 2,184 Testing & QA skills by installs in the Skillselion catalog
- Security screen: LOW risk (skills.sh audit)
- Data as of Jul 28, 2026 (Skillselion catalog sync)
database-design capabilities & compatibility
- Capabilities
- ask user for database preferences when unclear · choose database/orm based on context · don't default to postgresql for everything · asked user about database preference? · chosen database for this context?
- Use cases
- documentation
What database-design says it does
description: "Database design principles and decision-making. Schema design, indexing strategy, ORM selection, serverless databases."
Learn to THINK, not copy SQL patterns.
npx skills add https://github.com/sickn33/antigravity-awesome-skills --skill database-designAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 1.8k |
|---|---|
| repo stars | ★ 44k |
| Security audit | 3 / 3 scanners passed |
| Last updated | July 27, 2026 |
| Repository | sickn33/antigravity-awesome-skills ↗ |
What problem does database-design solve for developers using the documented workflows?
"Database design principles and decision-making. Schema design, indexing strategy, ORM selection, serverless databases."
Who is it for?
Developers working with database-design patterns described in the skill documentation.
Skip if: Skip when docs are empty or the task is outside the skill documented scope.
When should I use this skill?
Use when "Database design principles and decision-making. Schema design, indexing strategy, ORM selection, serverless databases."
What you get
Actionable database-design guidance grounded in SKILL.md workflows and reference files.
- Database recommendation
- Indexing strategy direction
By the numbers
- Decision tree covers 8 database options including PostgreSQL, Neon, Supabase, Turso, SQLite, pgvector, PlanetScale, and
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
When to Use
This skill is applicable to execute the workflow or actions described in the overview.
Limitations
- Use this skill only when the task clearly matches the scope described above.
- Do not treat the output as a substitute for environment-specific validation, testing, or expert review.
- Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.
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
How it compares
Use this for early datastore selection and indexing direction rather than SQL query tuning or ORM configuration skills.
FAQ
Who is database-design for?
Developers and software engineers working with database-design patterns described in the skill documentation.
When should I use database-design?
When "Database design principles and decision-making. Schema design, indexing strategy, ORM selection, serverless databases.".
Is database-design safe to install?
Review the Security Audits panel on this page before installing in production.