本文へ移動
cccskills
無料GitHub で公開

database-design

Design relational database schemas (and choose when to go NoSQL) that stay maintainable and fast. Use this skill whenever the user mentions tables, DDL, entities and relationships, normalization (1NF/2NF/3NF), primary and foreign keys, UUID vs bigint IDs, indexes (B-tree, composite, covering, partial), EXPLAIN, constraints (CHECK, UNIQUE, exclusion), transactions and isolation levels, migrations (Alembic, Prisma, Flyway, expand-contract, backfilling), or SQL vs NoSQL (MongoDB, DynamoDB, Cassandra, graph databases). Also trigger for "design the database", "model this domain", "which database should I use", or writing ORM models and migration files for PostgreSQL, MySQL, SQLite, or SQL Server.

インストール方法を見る

含まれるファイル(9)

  • SKILL.md17.5 KB
  • eval.yaml1.2 KB
  • graders/check.py8.2 KB
  • instructions/schema-design.md2.6 KB
  • references/indexing-and-query-tuning.md6.6 KB
  • references/migrations-zero-downtime.md5.9 KB
  • references/normalization-and-keys.md7.7 KB
  • rubrics/quality.md1.8 KB
  • solutions/reference-schema-design3.3 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

Database Design

Database design turns a domain into a schema that stays fast, correct, and easy to evolve for years. This skill covers the full pipeline — requirements analysis, entity modeling, normalization, keys, constraints, indexes, and safe migrations — plus deciding when a document, wide-column, or graph store beats a relational database.

Quick Reference

TopicReference
Normalization worked examples, natural vs surrogate keys, UUID vs bigintnormalization-and-keys.md
B-tree internals, composite/covering/partial indexes, reading EXPLAINindexing-and-query-tuning.md
Migration tools (Alembic, Prisma, Flyway), expand-contract, backfillingmigrations-zero-downtime.md

Core Workflow

Work through these steps in order — each informs the next, and skipping requirements analysis is the most common source of bad schemas.

  1. Gather requirements. List entities, attributes, and relationships. Note cardinalities and whether each read is CRUD (single-row) or reporting (aggregate). Ask about scale, growth, retention, and compliance (e.g. GDPR erasure).
  2. Model entities and relationships. Draw an ER sketch. Normalize to 3NF by default; denormalize only later, with a measured reason.
  3. Choose keys. Prefer surrogate BIGINT IDENTITY primary keys unless a natural key is genuinely stable. Decide UUID vs bigint now — changing it later is painful.
  4. Add constraints. NOT NULL, UNIQUE, CHECK, defaults, and foreign keys belong in the database, not just in the ORM.
  5. Design indexes. Start with the indexes backing PK/FK/UNIQUE constraints, then add query-driven indexes for the hot paths found in step 1.
  6. Validate with EXPLAIN. Run EXPLAIN (ANALYZE, BUFFERS) against realistic data. Fix the plan, not the schema, before considering denormalization.
  7. Plan migrations. Versioned migrations in code; expand-contract for anything touching a live table. Never hand-edit production.

Requirements Analysis

Collect these before writing a single CREATE TABLE:

QuestionWhy it matters
What are the entities and their attributes?Defines tables and columns
What are the relationships and cardinalities?1:1, 1:N, M:N (junction table)
Required or optional attributes?NOT NULL vs NULLable
Is a read CRUD or reporting?CRUD wants normalized lookups; reporting wants aggregates, maybe denormalized
Write volume and read/write ratio?Drives index count and normalization level
Data growth and retention?Partitioning, archival, time-series decisions
Consistency requirements?Isolation levels; whether eventual consistency is acceptable
Compliance (GDPR, HIPAA, finance)?Audit columns, soft vs hard deletes, retention rules

CRUD vs reporting reads want opposite schema shapes: CRUD queries touch few rows, narrow columns, and normalized tables; reporting wants few tables, wide pre-joined rows, and precomputed aggregates. If both matter, keep the OLTP schema normalized and serve reporting from a separate path (materialized views, a read replica, or a warehouse). Cardinality:

RelationshipModel
1:1FK with UNIQUE, or merge into one table when always accessed together
1:NForeign key on the "many" side
M:NJunction table with two FKs, composite PK over both

Normalization (1NF–3NF)

Normalization removes redundancy so each fact is stored and updated in exactly one place.

FormRuleTypical violationFix
1NFAtomic values; no repeating groupsphones column holding "555-1,555-2"Child table, one row per value
2NFNo partial dependency on part of a composite keyorder_item storing product_name (depends only on product_id)Move it to product
3NFNo transitive dependency on a non-key columnorder storing customer_city (depends on customer_id, not order_id)Move it to customer

Normalize to 3NF by default. Denormalize deliberately — copy or aggregate data to serve a specific hot read — only when a measured query needs it. The costs are real: write amplification (every write maintains the copies), risk of drift, and backfill work whenever the derivation logic changes. Full worked example from spreadsheet to 3NF: normalization-and-keys.md.

Keys

Natural vs surrogate:

Natural keySurrogate key
Examplesisbn, email, slug, country_codeid BIGINT GENERATED ALWAYS AS IDENTITY
ProsMeaningful, real-world stable, no extra column for lookupsNever changes, compact, no domain coupling, DB-generated
ConsCan change or be re-issued; may be long or non-uniformMeaningless (still need UNIQUE business keys); opaque joins
RoleAdd as a UNIQUE business keyPrimary key for most tables

Foreign keys and referential actions:

ActionBehaviorUse when
RESTRICT / NO ACTIONRefuse to delete a referenced rowDefault; safest
CASCADEDelete children with the parentOwner-child lifecycles (order → items); audit the blast radius first
SET NULLNull out the child FKOptional references (deleted user keeps orders)

UUID vs bigint (full comparison in normalization-and-keys.md): bigint is 8 bytes, sequential, and cache-friendly — prefer it for high-write OLTP. UUIDv7 (time-ordered) is the choice for distributed or client-generated IDs where a central sequence is impossible. Avoid random UUIDv4 as a PK on hot tables: random inserts thrash the B-tree and bloat indexes.

Indexing

A B-tree index is an ordered copy of one or more columns that lets the engine find rows without scanning the whole table — O(log n) equality lookups and efficient range scans. Design indexes for your queries, not for every column.

  • Composite index column order matters. Put equality columns first, then range/ORDER BY columns: (customer_id, created_at) serves WHERE customer_id = ? AND created_at > ?. A leading range column makes the later columns useless for lookups.
  • Covering indexes include every column the query touches (INCLUDE (status)) so the engine can answer from the index alone (index-only scan).
  • Partial indexes carry a WHERE clause — e.g. WHERE status = 'pending' — keeping a hot subset small: faster scans, fewer writes to maintain.
  • When an index hurts: every INSERT/UPDATE/DELETE maintains every index on the table (write amplification); indexes consume disk and buffer cache; unused indexes still cost writes. Remove indexes no query uses.
  • EXPLAIN is the source of truth. EXPLAIN (ANALYZE, BUFFERS) on a slow query shows Seq Scan vs Index Scan vs joins and where time actually goes. Reading guide: indexing-and-query-tuning.md.

Constraints

Constraints make the database enforce your invariants, so app bugs and concurrent writers cannot corrupt data:

ConstraintExamplePurpose
NOT NULLemail TEXT NOT NULLColumn is always present
UNIQUEUNIQUE (tenant_id, slug)No duplicates within scope
CHECKCHECK (quantity > 0)Value sanity and business rules
DEFAULTcreated_at TIMESTAMPTZ NOT NULL DEFAULT now()Fills values on insert
Foreign keyFOREIGN KEY (customer_id) REFERENCES customers(id)Referential integrity
EXCLUDE (PostgreSQL)EXCLUDE USING gist (room WITH =, during WITH &&)No overlapping reservations

Why they belong in the DB rather than the ORM: enforced under concurrency, enforced for every code path (imports, ad-hoc SQL, future apps), and they document the schema's contract. ORM-level validation is a convenience; DB constraints are the guarantee.

Transactions and Isolation

ACID transactions keep multi-step writes atomic. The isolation level is a consistency-vs-throughput tradeoff:

LevelPreventsCan still see
Read committed (default in PostgreSQL/MySQL)Dirty readsNon-repeatable reads, phantoms
Repeatable readDirty and non-repeatable readsPhantoms (PostgreSQL also prevents these here)
SerializableDirty, non-repeatable, phantoms, write skew— (at a concurrency cost)

Locking strategies:

  • Pessimistic: SELECT ... FOR UPDATE locks rows so no one else modifies them until commit. Simple to reason about; hurts under contention.
  • Optimistic: read a version/rowversion column and UPDATE only if unchanged (WHERE version = ?), retrying on conflict. Scales better; needs retry logic.

Rule of thumb: start at read committed; raise the level only for a concrete anomaly (e.g. financial invariants); prefer optimistic locking over long-held locks.

Migrations

Schema changes are code: versioned, reviewed, tested, and applied exactly once in order. Tools: Alembic (Python/SQLAlchemy), Prisma Migrate (TypeScript), Flyway (SQL-first, JVM/CLI).

# Alembic
alembic revision --autogenerate -m "add orders table"
alembic upgrade head

# Prisma
prisma migrate dev --name add_orders

# Flyway (versioned SQL files, e.g. V2__add_orders.sql)
flyway migrate

Expand–contract (a.k.a. expand–migrate–contract) is the zero-downtime pattern for anything touching a live table:

  1. Expand — add the new column/table as additive (nullable or new); deploy code that writes both old and new.
  2. Backfill — populate the new structure in bounded batches without blocking writes.
  3. Contract — switch reads, then writes, then drop the old structure once nothing references it.
-- 1. Expand: add nullable column, dual-write in the app
ALTER TABLE orders ADD COLUMN total_cents BIGINT;

-- 2. Backfill in batches
UPDATE orders SET total_cents = /* recompute from items */
WHERE id BETWEEN :start AND :end AND total_cents IS NULL;

-- 3. Contract: flip reads, then drop the old column
ALTER TABLE orders ALTER COLUMN total_cents SET NOT NULL;
-- later: ALTER TABLE orders DROP COLUMN legacy_total;

Backfilling runs in bounded batches (WHERE id > :last_id ORDER BY id LIMIT 1000) so it neither locks the table for minutes nor floods the WAL. Never backfill a large table with a single unbounded UPDATE. Full guide with locking gotchas: migrations-zero-downtime.md.

SQL vs NoSQL

Start from the workload, not the hype:

StoreStrengthsPick whenAvoid when
Relational (PostgreSQL, MySQL)Joins, transactions, constraints, ad-hoc queriesData has relationships and invariants; reporting; moneyHorizontal write scale beyond a single DB is the top need
Document (MongoDB)Flexible schemas, natural aggregates, fast single-doc readsDocument-shaped data, read-mostly, evolving attributesCross-document transactions/joins are core; strong invariants
Wide-column (Cassandra, DynamoDB)Linear read/write scale, partition-friendlyKnown access patterns, huge scale, time-series at scaleAd-hoc queries, joins, evolving query patterns
Graph (Neo4j)Traversal of relationshipsDeep relationship queries (fraud, social, routing)Simple CRUD, bulk reporting

A pragmatic middle path: keep the relational DB as the system of record and add specialized stores (search, cache, analytics warehouse) around it — don't fork the domain model across stores unnecessarily.

Practical Patterns

PatternHowGotchas
JSON columnsdata JSONB for rarely-queried flexible attributes; GIN index only if you filter on themDon't put query-critical or joined data in JSON
Full-text searchPostgreSQL tsvector + GIN, MySQL FULLTEXTMove to OpenSearch/Elasticsearch past ~1M docs or for ranking complexity
Time-seriesTimescaleDB hypertables or range partitioning by timeKeep recent partitions small; retention via DROP PARTITION
Soft deletesdeleted_at TIMESTAMPTZ NULLBreaks UNIQUE constraints and FKs — filter everywhere, or hard delete + audit table
Audit columnscreated_at, updated_at, created_by; triggers or ORM callbacksupdated_at needs a trigger for raw-SQL writes; full history needs event sourcing
N+1 preventionJOINs, IN (...) batching, ORM eager loadingN+1 = 1 query for N parents + N queries for children
-- N+1 anti-pattern: 1 query for orders + N queries for order_items. Fix: one query
SELECT o.*, oi.*
FROM orders o
JOIN order_items oi ON oi.order_id = o.id
WHERE o.customer_id = $1;

Worked Example: Small E-Commerce

Domain: customers, products (each in many categories), orders (many items, each item is one product). Requirements: order CRUD, product browsing by category, "recent orders for a customer" reporting, and a search box.

erDiagram
    CUSTOMER ||--o{ "ORDER" : places
    "ORDER" ||--|{ ORDER_ITEM : contains
    PRODUCT ||--o{ ORDER_ITEM : "is ordered as"
    PRODUCT ||--o{ PRODUCT_CATEGORY : has
    CATEGORY ||--o{ PRODUCT_CATEGORY : has
    CUSTOMER {
        bigint id PK
        text email UK
        text name
        timestamptz created_at
    }
    "ORDER" {
        bigint id PK
        bigint customer_id FK
        text status
        bigint total_cents
        timestamptz created_at
    }
    ORDER_ITEM {
        bigint order_id PK,FK
        bigint product_id PK,FK
        int quantity
        bigint unit_price_cents
    }
    PRODUCT_CATEGORY {
        bigint product_id PK,FK
        bigint category_id PK,FK
    }
    PRODUCT {
        bigint id PK
        text sku UK
        text name
        text description
        tsvector search_vector
    }
    CATEGORY {
        bigint id PK
        text slug UK
    }

Key decisions:

  • Keys: surrogate bigint PKs everywhere; sku, email, slug as UNIQUE natural keys for lookups.
  • Normalization: 3NF — product and category are separate with a junction table. orders.total_cents is a deliberate denormalized aggregate, recomputed in the same transaction as its items.
  • Constraints: CHECK quantity > 0 and unit_price_cents >= 0; CHECK on status; FK ON DELETE RESTRICT for products/categories, CASCADE for order items; the junction's composite PK already enforces uniqueness.
  • Indexes:
-- Hot paths
CREATE INDEX idx_orders_customer_created ON orders (customer_id, created_at DESC); -- "recent orders" (equality first, then sort)
CREATE INDEX idx_order_items_order ON order_items (order_id);                      -- order detail
CREATE INDEX idx_products_search ON products USING gin (search_vector);            -- search box (tsvector kept fresh by a trigger)
CREATE INDEX idx_orders_status_created ON orders (status, created_at)
    WHERE status = 'pending';                                                      -- partial: tiny fulfillment queue

The composite (customer_id, created_at) serves both WHERE customer_id = ? and ORDER BY created_at DESC. The partial index stays tiny because only pending orders enter the queue.

Anti-Patterns to Avoid

  • No requirements analysis — building tables before knowing queries, cardinalities, and read patterns.
  • Premature denormalization — copying data "for performance" before EXPLAIN shows a problem.
  • Mutable natural keys as PK (email, username) — churn breaks every referencing row.
  • Random UUIDv4 PKs on hot tables — random inserts fragment the B-tree and bloat indexes.
  • Index on every column — each index costs writes; unused ones are pure overhead.
  • Constraints only in the ORM — race conditions and raw SQL bypass validation.
  • Soft deletes without a plan — deleted_at silently breaks UNIQUE constraints, and every query needs WHERE deleted_at IS NULL.
  • SELECT * in production queries — defeats covering indexes and widens scans.
  • Giant or hand-applied migrations — schema changes must be small, versioned, and reversible.
  • EAV (entity-attribute-value) tables — "flexible" schemas that make every query painful.

When to Use / Not Use

Use this skill when:

  • Designing a new schema from requirements or a domain description
  • Reviewing an existing schema for normalization, key, constraint, or index problems
  • Deciding between SQL and NoSQL for a workload
  • Planning a migration, backfill, or zero-downtime schema change
  • Tuning slow queries with EXPLAIN

Do NOT use when:

  • The task is only writing queries against an existing, settled schema (no design decisions)
  • You need a runbook for a specific DB's operations (backups, failover, tuning knobs) — that is ops, not design
  • Deep implementation work inside a NoSQL store (DynamoDB partition keys, Cassandra compaction) — this skill covers choosing the store, not its internal best practices
  • The user just needs boilerplate ORM models generated from an already-decided schema

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

同じリポジトリのスキル

概要と使いどころ

Adaption AI SDK for synthetic data augmentation and dataset adaptation. Use when building data pipelines with the Adaption Python SDK, uploading datasets (local files, Hugging Face, Kaggle), running augmentation/adaptation jobs, configuring brand controls (hallucination mitigation, safety categories, length), recipe specifications (reasoning traces, deduplication, preference pairs, prompt rephrase), evaluating dataset quality, downloading results, or any workflow involving `pip install adaption`, `from adaption import Adaption`, Adaptive Data, or the adaptionlabs.ai API. Also trigger when the user mentions synthetic data generation for fine-tuning, dataset augmentation pipelines, DPO preference pair generation, or grounding-based hallucination reduction on training data.

日本語の概要は準備中です。原文の説明を表示しています。

svngoku/coding-agents-skills122026年8月14日 更新

Design and review intuitive, scalable, maintainable HTTP APIs. Use this skill whenever the user wants to design a new REST API, review an existing API or spec, write OpenAPI 3.x definitions, or work with HTTP semantics (GET/POST/PUT/PATCH/DELETE), status codes, idempotency (Idempotency-Key), error envelopes (RFC 7807 problem+json), pagination, filtering, versioning, or API auth (API keys, OAuth2 client credentials, rate limits). Also trigger for "API design", "RESTful", "endpoints", "OpenAPI", "Swagger", "ReDoc", "contract testing", or GraphQL and gRPC design questions.

日本語の概要は準備中です。原文の説明を表示しています。

svngoku/coding-agents-skills122026年8月14日 更新

ddd

無料

Domain-Driven Design system for software development. Use when designing new systems with DDD principles, refactoring existing codebases toward DDD, generating code scaffolding (entities, aggregates, repositories, domain events), facilitating Event Storming sessions, creating bounded context maps, or performing code reviews with a DDD lens. Covers both strategic design (bounded contexts, subdomains, context maps, ubiquitous language) and tactical design (entities, value objects, aggregates, domain services, repositories). Supports all major architecture patterns (Hexagonal/Ports & Adapters, CQRS, Event Sourcing, Clean Architecture) with language-agnostic guidance and concrete examples in Python and TypeScript.

日本語の概要は準備中です。原文の説明を表示しています。

svngoku/coding-agents-skills122026年8月14日 更新

genai-tk

無料

Build GenAI and agentic applications with the genai-tk toolkit (https://github.com/tclatos/genai-tk) — a YAML-driven wrapper over LangChain, LangGraph, and 100+ LLM providers. Use this skill whenever the user mentions genai-tk, genai_tk, the GenAI Toolkit, `cli init`, `LangchainAgent`, `get_llm`/`get_embeddings`, `RetrieverFactory`/`ManagedRetriever`, the four bundled agent frameworks (ReAct, Deep, Deer-flow, SmolAgents), the OpenSandbox Docker integration, the `model_id@provider` identifier format, the `global_config()`/`OmegaConfig` system with `app_conf.yaml` and `:merge`, BAML structured extraction, SkillsMiddleware, writing or editing the toolkit's YAML profiles (langchain.yaml, deerflow.yaml, llm.yaml, retrievers.yaml), composing retrievers (vector/bm25/ensemble/reranked/pg_hybrid/zero_entropy), or extending the CLI with `CliTopCommand`. Trigger even when the user only says "the toolkit" in context.

日本語の概要は準備中です。原文の説明を表示しています。

svngoku/coding-agents-skills122026年8月14日 更新

langchain

無料

Build AI agents with LangChain framework. Use when building agents, tools, memory, MCP integrations, RAG pipelines, multi-agent systems, or any LLM-powered applications using LangChain or LangGraph in Python or TypeScript.

日本語の概要は準備中です。原文の説明を表示しています。

svngoku/coding-agents-skills122026年8月14日 更新

Decompose systems into microservices and apply canonical distributed-systems patterns. Use this skill whenever the user wants to split a monolith into services, design service boundaries, choose between microservices and a modular monolith, implement sagas or the outbox pattern, set up CQRS or event sourcing, configure an API gateway or BFF, add resilience (circuit breakers, retries, timeouts), or implement distributed tracing with OpenTelemetry. Also trigger for distributed transactions, service discovery, event-driven architecture, contract testing with Pact, canary releases, and idempotent consumers.

日本語の概要は準備中です。原文の説明を表示しています。

svngoku/coding-agents-skills122026年8月14日 更新

svngoku のスキルをすべて見る

このスキルの問題を報告する