kid-sid/claude-spellbook/database-design
Claude Code and agent skill by kid-sid/claude-spellbook
- community
Checking that the SKILL.md file is still in the repository.
Use when designing a relational schema — normalization (1NF–3NF), primary key strategy, modelling relationships, naming conventions, or planning a zero-downtime migration with the expand-contract pattern. For writing and tuning queries, indexes, or EXPLAIN ANALYZE, use postgresql.
Install
npx vskill@latest install kid-sid/claude-spellbook/database-designSKILL.md
Database Design
A practical reference for designing, indexing, migrating, and operating relational databases in production, with PostgreSQL as the primary target.
When to Activate
- Designing a new database schema or data model
- Adding indexes to improve query performance
- Writing or reviewing a database migration
- Optimizing a slow SQL query
- Choosing between normalization and denormalization strategies
- Setting up connection pooling for a service
- Planning a zero-downtime schema change in production
Schema Design Principles
Normalization
First Normal Form (1NF) — atomic values, no repeating groups.
Second Normal Form (2NF) — no partial dependencies on a composite key. Every non-key column must depend on the whole key, not just part of it.
Third Normal Form (3NF) — no transitive dependencies. Non-key columns must not depend on other non-key columns.
Deliberate denormalization — acceptable in specific scenarios; always document the reason.
| Scenario | Denormalization Pattern | Document as | |
|---|---|---|---|
| Reporting / analytics tables | Pre-aggregated summary columns | -- DENORM: avoids JOIN on reporting queries | |
| Heavy read workload | Duplicated display name on child table | -- DENORM: read:write ratio > 100:1 | |
| Caching aggregates | total_order_count on users table | -- DENORM: updated by trigger, cache of COUNT(orders) |
Primary Key Strategies
| Strategy | Type | Pros | Cons | Best For | |
|---|---|---|---|---|---|
BIGSERIAL / auto-increment | 8-byte integer | Simple, small, ordered, fast joins | Leaks row count; bad for distributed inserts | Single-database apps, internal IDs | |
| UUID v4 | 16-byte random | Globally unique, no ordering | Index fragmentation, 16 bytes, not sortable | Distributed systems (legacy) | |
| UUID v7 | 16-byte time-ordered | Globally unique, time-sortable, B-tree friendly | Slightly larger than integer | New distributed systems (preferred) | |
| Natural key | Varies | Human-readable, no surrogate needed | Hard to change; rarely truly immutable | ISO country codes, currency codes |
Use BIGSERIAL for most tables. Prefer UUID v7 over UUID v4 for distributed or externally-exposed IDs.
Data Type Selection
| Use Case | Preferred Type | Avoid | Reason | |
|---|---|---|---|---|
| Short text | VARCHAR(n) or TEXT | CHAR(n) | CHAR pads with spaces, wastes storage | |
| Timestamps | TIMESTAMPTZ | TIMESTAMP | TIMESTAMP has no timezone — silent bugs in multi-region apps | |
| Money / currency | NUMERIC(10,2) | FLOAT / DOUBLE PRECISION | Floating point errors accumulate in financial calculations | |
| Semi-structured data | JSONB | JSON | JSONB is binary, indexed, and faster to query | |
| Boolean | BOOLEAN | INT (0/1) | Semantic clarity; BOOLEAN accepts TRUE/FALSE/NULL | |
| Enums | Lookup table or TEXT CHECK | PostgreSQL ENUM type | ENUM requires ALTER TYPE to add values; lookup tables are easier to extend |
Naming Conventions
- Tables:
snake_case, plural —users,order_items,audit_logs - Columns:
snake_case, singular —user_id,created_at,is_active - Foreign keys:
<referenced_table_singular>_id—user_idreferencesusers(id) - Indexes:
idx_<table>_<columns>—idx_users_email,idx_orders_user_id_created_at - Unique constraints:
uq_<table>_<col>—uq_users_email - Foreign key constraints:
fk_<table>_<referenced>—fk_orders_users - Check constraints:
ck_<table>_<rule>—ck_products_price_positive
Relationships and Foreign Keys
One-to-Many
The "many" side holds the foreign key column.
Cascade options:
| ON DELETE Behavior | When to Use | |
|---|---|---|
CASCADE | Child rows are meaningless without the parent (e.g., post comments deleted when post is deleted) | |
SET NULL | Child row survives but loses its association (e.g., assigned user deleted, task becomes unassigned) | |
RESTRICT | Prevent deletion of parent if children exist — use when you want explicit cleanup | |
NO ACTION | Same as RESTRICT but deferred; default if unspecified — almost always specify explicitly |
Many-to-Many
Use a junction table with a composite primary key. Always include created_at.
Adding created_at costs nothing and you will always want it when auditing membership changes.
Polymorphic Associations
Anti-pattern — using entity_type + entity_id with a single generic foreign key column breaks referential integrity because PostgreSQL cannot enforce a foreign key across multiple tables.
Preferred pattern — separate join tables per entity type, each with a proper foreign key.
Indexing Strategy
Index Types
| Type | When to Use | PostgreSQL Syntax | |
|---|---|---|---|
| B-tree | Equality and range queries; default for most columns | CREATE INDEX idx_name ON tbl (col) | |
| Hash | Equality-only predicates; slightly faster than B-tree for equality | CREATE INDEX idx_name ON tbl USING HASH (col) | |
| GIN | JSONB fields, arrays, full-text search (tsvector) | CREATE INDEX idx_name ON tbl USING GIN (col) | |
| GiST | Geometric data, PostGIS, range types (tsrange, int4range) | CREATE INDEX idx_name ON tbl USING GIST (col) | |
| Partial | Index a filtered subset of rows | CREATE INDEX idx_name ON tbl (col) WHERE condition |
Composite Index Column Order
Rule: put equality predicate columns first, range predicate columns last.
Covering index — include non-key columns with INCLUDE to avoid a heap fetch (index-only scan).
Index Bloat
This is the start of the file. Read the full SKILL.md on GitHub.
Security
- Security scanPassed, 100 of 100Pattern checks on the skill's files.
- Model reviewPassed
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingskills/database-design/skill.md
Popularity
- Repository stars
- 186
- Repository forks
- 15
- 7-day trend score
- 26
Stars and forks are for the whole GitHub repository, not this skill alone. Not refreshed yet.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/kid-sid/claude-spellbook/database-design)