원클릭으로
database-design
Database design principles and decision-making. Schema design, indexing strategy, ORM selection, serverless databases.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Database design principles and decision-making. Schema design, indexing strategy, ORM selection, serverless databases.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
Senior agent organizer with expertise in assembling and coordinating multi-agent teams. Your focus spans task analysis, agent capability mapping, workflow design, and team optimization.
AI agent design principles. Agent loops, tool calling, memory architectures, multi-agent coordination, human-in-the-loop gates, and guardrails. Use when building AI agents, autonomous workflows, or any system where an LLM plans and executes multi-step tasks.
API design principles and decision-making. REST vs GraphQL vs tRPC selection, response formats, versioning, pagination.
Main application building orchestrator. Creates full-stack applications from natural language requests. Determines project type, selects tech stack, coordinates agents.
Architectural decision-making framework. Requirements analysis, trade-off evaluation, ADR documentation. Use when making architecture decisions or analyzing system design.
Bash/Linux terminal patterns. Critical commands, piping, error handling, scripting. Use when working on macOS or Linux systems.
| name | database-design |
| description | Database design principles and decision-making. Schema design, indexing strategy, ORM selection, serverless databases. |
| allowed-tools | Read, Write, Edit, Glob, Grep |
| version | 1.0.0 |
| last-updated | "2026-03-12T00:00:00.000Z" |
| applies-to-model | gemini-2.5-pro, claude-3-7-sonnet |
A schema is cheap to design and expensive to migrate. Design it right for the queries your app actually runs.
Before schema design, the database type must be justified — not assumed.
| Need | Consider |
|---|---|
| Relational data with integrity constraints | PostgreSQL (default choice for most apps) |
| Horizontal write scaling, flexible schema | MongoDB, DynamoDB |
| Sub-millisecond reads, ephemeral/session data | Redis, Upstash |
| Full-text search as primary use case | Elasticsearch, Typesense |
| Serverless, zero-ops, edge-deployable | Turso, PlanetScale, Neon |
| Time-series events | InfluxDB, TimescaleDB |
| Semantic / vector similarity search | pgvector (in PostgreSQL), Qdrant, Pinecone |
Default when uncertain: PostgreSQL. It handles relational, JSON, full-text, and time-series use cases well enough that you rarely need to deviate for most applications.
AI applications need semantic search — finding documents by meaning, not keyword. Vector databases store high-dimensional embeddings and search them by similarity.
-- Enable extension once
CREATE EXTENSION IF NOT EXISTS vector;
-- Add embedding column to existing table
ALTER TABLE documents ADD COLUMN embedding vector(1536); -- 1536 for text-embedding-3-small
-- IVFFlat index for approximate nearest neighbor search
CREATE INDEX ON documents USING ivfflat (embedding vector_cosine_ops) WITH (lists = 100);
-- lists = sqrt(num_rows) is a good starting point
-- Query: find 5 most semantically similar documents
SELECT id, content, 1 - (embedding <=> $1) AS similarity
FROM documents
ORDER BY embedding <=> $1 -- cosine distance operator
LIMIT 5;
| Trigger to Upgrade | Recommended |
|---|---|
| > 1M vectors + sub-10ms p99 | Qdrant (self-hosted, Rust) or Pinecone (managed) |
| Multimodal (text + images) | Weaviate |
| Managed, predictable pricing | Pinecone |
| Zero-ops prototype | ChromaDB (local) |
// Always store both the raw text AND the embedding — embeddings are not reversible
await db.query(`
INSERT INTO documents (content, source_url, chunk_index, embedding)
VALUES ($1, $2, $3, $4)
`, [chunkText, sourceUrl, chunkIndex, JSON.stringify(embedding)]);
// embedding is float[] — serialize to JSON for parameterized query
The most normalized schema is not always the right schema. Ask: what does the application actually read?
Design the schema to make the most frequent, performance-critical queries fast — even if that means some denormalization.
-- Tables: plural, snake_case
CREATE TABLE user_sessions (...);
-- Primary keys: always "id"
id UUID PRIMARY KEY DEFAULT gen_random_uuid();
-- Foreign keys: {referenced_table_singular}_id
user_id UUID REFERENCES users(id);
-- Timestamps: always include both
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW();
-- Booleans: is_ prefix
is_active BOOLEAN NOT NULL DEFAULT TRUE;
id UUID PRIMARY KEY -- or BIGSERIAL for high-insert tables
created_at TIMESTAMPTZ -- immutable creation time
updated_at TIMESTAMPTZ -- changes on every update (trigger or ORM)
An index makes reads faster and writes slightly slower. Index on the columns you filter and sort — not every column.
Index when:
WHERE clauses frequentlyJOIN conditionsORDER BY on large result setsDon't index when:
-- Composite index: order matters — most selective first
CREATE INDEX idx_orders_user_status ON orders(user_id, status);
-- Partial index: only index what you query
CREATE INDEX idx_active_users ON users(email) WHERE is_active = TRUE;
The most common ORM performance failure. N+1 happens when you fetch N records then make a separate query for each one.
// ❌ N+1 — 1 query for posts + N queries for authors
const posts = await Post.findAll();
for (const post of posts) {
post.author = await User.findById(post.userId); // N queries
}
// ✅ Eager load — 2 queries total
const posts = await Post.findAll({ include: ['author'] });
Detection: Enable query logging in development. If you see repetitive queries differing only by ID, you have N+1.
| File | Covers | Load When |
|---|---|---|
schema-design.md | Detailed schema patterns and relationship modeling | Designing or reviewing a schema |
indexing.md | When and how to index, partial indexes, covering indexes | Performance investigation |
orm-selection.md | Prisma vs Drizzle vs TypeORM vs raw SQL trade-offs | Choosing ORM |
migrations.md | Safe migration patterns, rollback strategy | Changing existing schema |
optimization.md | Query analysis, EXPLAIN output, common fixes | Slow query diagnosis |
database-selection.md | Detailed database selection framework | Architecture decision |
| Script | Purpose | Run With |
|---|---|---|
scripts/schema_validator.py | Validates schema for missing indexes, naming issues | python scripts/schema_validator.py <project_path> |
When this skill produces a recommendation or design decision, structure your output as:
━━━ Database Design Recommendation ━━━━━━━━━━━━━━━━
Decision: [what was chosen / proposed]
Rationale: [why — one concise line]
Trade-offs: [what is consciously accepted]
Next action: [concrete next step for the user]
─────────────────────────────────────────────────
Pre-Flight: ✅ All checks passed
or ❌ [blocking item that must be resolved first]
Slash command: /tribunal-database
Active reviewers: logic · security · sql
VARCHAR(255) for everything instead of precise types or TEXT.updated_at triggers — defining updated_at without a mechanism to actually update it.Review these questions before generating database schemas or queries:
✅ Did I design for the queries the application actually runs, rather than theoretical elegance?
✅ Are my suggested indexes selective and actually used in `WHERE` or `JOIN` clauses?
✅ Is this code safe from N+1 query performance problems?
✅ Did I rely on parameterized queries (no string concatenation)?
✅ Did I use the correct primary key strategy (e.g., UUID vs BIGSERIAL) for the scale?
AI coding assistants often fall into specific bad habits when dealing with this domain. These are strictly forbidden:
// VERIFY or check package.json / requirements.txt.Slash command: /review or /tribunal-full
Active reviewers: logic-reviewer · security-auditor
// VERIFY: [reason].Review these questions before confirming output:
✅ Did I rely ONLY on real, verified tools and methods?
✅ Is this solution appropriately scoped to the user's constraints?
✅ Did I handle potential failure modes and edge cases?
✅ Have I avoided generic boilerplate that doesn't add value?
CRITICAL: You must follow a strict "evidence-based closeout" state machine.