agentsclimarketplace

Data modeling

Skill muxammadmamajonov/dot-claude/.claude/skills/data-modeling

Design entities, relationships, constraints, indexes, and safe migrations from requirements and architecture. Use before persistence code, when reshaping an entity, or on query/integrity problems.From its SKILL.md

Install
npx -y skills add muxammadmamajonov/dot-claude --skill data-modeling

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

SKILL.md

15.4 KB, ~3.3k tokens by cl100k_base, as published. Nobody here has run it

Data Modeling

When to use

  • After architecture (.claude/skills/architecture/SKILL.md) defines components and their owned data, before persistence code is written.
  • When introducing a new domain entity or significantly reshaping an existing one.
  • When integrity bugs, slow queries, or scaling limits trace back to schema or indexing.
  • When evaluating a storage-paradigm change (e.g., adding a document store or time-series DB alongside relational tables).

Workflow

Phase 1 — Domain Extraction (Inputs → Conceptual Model)

1. Gather inputs. Collect docs/requirements.md, docs/architecture/overview.md, and any existing docs/data-model.md. Pull the entity vocabulary directly from requirements — what nouns does the business actually name? (user, order, subscription, device, transaction, job, session, etc.)

2. List entities, attributes, and relationships. For each entity: name, description in one plain sentence, the key attributes (name, type, constraints), and the lifecycle states it passes through. For each relationship: which entities, what cardinality (one-to-one / one-to-many / many-to-many), whether it is optional or mandatory on each side, and what the relationship itself means in business terms.

3. Validate against the domain, not the UI. Examine every entity and ask: does this appear in the business language, or did it come from a UI screen or implementation artifact? Remove or rename anything that is a UI concern masquerading as a domain entity. This is the single most common source of brittle schemas.

4. Produce a conceptual ER diagram. Use Mermaid (erDiagram). Show entities, key attributes, cardinality notation (||, }|, |{, etc.), and relationship labels. Share with a domain expert or product owner for sign-off before proceeding — changes here are cheap; changes to a deployed schema are expensive.


Phase 2 — Logical Design (Paradigm + Keys + Normalization)

5. Choose the storage paradigm per data set. Evaluate against actual access patterns, not general preference. Use the stack decision in docs/stack.md as the anchor; this step may propose additions.

PatternChoose whenAvoid when
Relational (SQL)Complex joins, strong integrity, ACID transactions, ad-hoc queriesSchema changes very frequently, document varies wildly per row
Document (NoSQL)Aggregate-oriented reads, flexible/optional structure, hierarchical dataNeed cross-document transactions or complex multi-collection joins
Key-valueCaches, sessions, idempotency locks, countersNeed to query by anything other than the key
Wide-column / time-seriesHigh-volume append, time-windowed aggregates, IoT telemetryNeed strong relationships between records
GraphRelationship traversal is the primary operation (social graphs, recommendations, access-control graphs)Data is flat and tabular
Search index (e.g., Elasticsearch)Full-text search, faceted filtering, fuzzy matchSingle source of truth — always backed by a primary store
Object/blob storeBinary files, media, large payloadsQueryable structured data

Mixed paradigms are fine; each must be justified and documented.

6. Define primary keys and identity.

  • Prefer stable surrogate keys: UUIDv4 (random, privacy-safe), UUIDv7 / ULID (time-ordered, better index locality, recommended for high-insert tables).
  • Use natural keys only when they are truly immutable, unique, and meaningful to the business (e.g., ISO country code, ISIN for securities).
  • For distributed inserts without a coordinator, use client-generated UUIDv7/ULID — avoids round-trips and hotspot inserts.
  • Never expose internal sequential integers as public IDs; they leak record counts and are enumerable.

7. Normalize to 3NF first. Eliminate transitive and partial dependencies. Third normal form prevents anomalies (insert, update, delete). Document every deviation from 3NF with its rationale and consistency plan before accepting it.

8. Denormalize deliberately, not habitually. Denormalize only where a measured read pattern requires it and replication can be kept consistent. Acceptable denormalization patterns:

  • Materialized/computed columns maintained by the database engine.
  • Summary/rollup tables refreshed by a scheduled job or trigger — document the staleness window.
  • Embedded documents in a document store when the sub-entity is always read with its parent and never queried independently.
  • Read replicas / CQRS projections when read and write models genuinely diverge at scale.

Phase 3 — Constraints and Integrity

9. Apply NOT NULL, defaults, and uniqueness. Every column that must always have a value gets NOT NULL. Nullable columns are opt-in with a documented reason. Unique constraints enforce real-world uniqueness at the database level — email addresses, usernames, order numbers, idempotency keys. Do not rely on application code alone for uniqueness invariants.

10. Define foreign keys with explicit referential action. For every FK:

  • ON DELETE RESTRICT (default safe): block deletion of a parent that has children.
  • ON DELETE CASCADE: use only when child records are meaningless without the parent and bulk deletion is safe (e.g., cascade-delete line items when an order is hard-deleted).
  • ON DELETE SET NULL: use when the child should be orphaned rather than deleted (e.g., reassigning tasks when a user is deleted).
  • Document the choice; the wrong default silently corrupts data on bulk parent deletions.

11. Add CHECK constraints and enums. Database-level checks enforce domain rules: valid ranges, non-negative amounts, valid state transitions where the set is finite and stable. For state/status columns: use CHECK + a string enum or a lookup table (not an integer code). Use lookup tables when the set of values must be queryable and joinable (e.g., order_statuses).


Phase 4 — Index Design

12. Derive indexes from the actual query list. Write out every query the application will run (filter conditions, join conditions, sort order, aggregation keys). Only then design indexes to serve them. An index you cannot trace to a named query is a candidate for removal.

13. Apply index design rules.

  • Single-column index on a FK used in joins and on high-cardinality filter columns.
  • Composite index: column order matters — put the highest-cardinality equality filter first, then range columns, then the sort column. WHERE status = 'active' AND created_at > ? → index on (status, created_at).
  • Partial index: index only a subset of rows to save space and improve speed for sparse queries. Example: WHERE deleted_at IS NULL.
  • Covering index: include non-key columns in the index so the engine can answer a query from the index alone without a table lookup. Use for hot read paths.
  • Unique index: serves as both a uniqueness constraint and an index.
  • Full-text / vector index: use the engine's native FTS or a dedicated search index; do not emulate with LIKE.
  • Index every FK column that will be used to load children given a parent. Without this, child lookups full-scan the table.

14. Verify with EXPLAIN / query plans. Before finalizing, run EXPLAIN (ANALYZE) on the top 5 queries against representative data volumes. The plan should show index seeks / index scans, not sequential scans on large tables. Adjust composite key order if needed.

15. Identify and remove redundant indexes. Indexes that are a prefix-superset of another, or indexes on very low-cardinality columns (e.g., a boolean with 95% true), are often better removed. Document the decision.


Phase 5 — Sensitive Data, Scale, and Lifecycle

16. Classify and protect sensitive data. Produce a sensitive-data table: column, entity, classification (PII / PHI / PCI / internal-confidential), encryption requirement (at-rest only, field-level, tokenized), retention limit, and jurisdiction if relevant. Apply:

  • Encryption at rest for the whole database (standard, usually platform-default).
  • Field-level encryption for high-sensitivity columns (credit card tokens, SSNs, health data) that must be unreadable even to a compromised DB admin.
  • Tokenization for PCI-scoped data — store a token and let a PCI-compliant vault hold the real PAN.
  • Data minimization — do not collect data you do not need; delete it when retention expires.
  • Cross-reference .claude/checklists/security.md before finalizing.

17. Plan audit, history, and lifecycle.

  • Audit columns (created_at, updated_at, created_by, updated_by) on all mutable entities — use DB-level defaults/triggers so they cannot be omitted.
  • Soft delete (deleted_at TIMESTAMPTZ): prefer over hard delete for records with audit/legal requirements. Add a partial index on WHERE deleted_at IS NULL.
  • Immutable event log: for financial, compliance, or domain-event use cases, write events to an append-only table rather than mutating state. The current state is a projection.
  • Partitioning and archival: for high-volume tables (logs, events, telemetry), design range or list partitioning upfront. Define the archival/purge strategy before data accumulates.

Phase 6 — Migration Strategy

18. Version and sequence migrations. Every schema change is a migration file: sequentially numbered, named descriptively (0023_add_user_preferences_table.sql), stored in VCS, reviewed like code. Migrations run in order on deploy.

19. Write forward and rollback for every migration. Every migration has an up and a down. Test both. If a down cannot be written without data loss, that is a signal the change is destructive and needs additional review.

20. Use the expand/contract pattern for destructive changes. Never rename a column, drop a column, or change a type in a single deploy. Use three phases across three safe deploys:

  1. Expand: add the new column/table alongside the old one; start writing to both.
  2. Backfill: migrate existing data; verify completeness.
  3. Contract: switch all reads to the new; remove the old column in a later deploy once confident.

This makes every schema change zero-downtime and independently reversible.

21. Guard destructive migrations. Any migration that drops columns, drops tables, truncates data, or changes column types in a narrowing direction is destructive and requires:

  • Explicit human approval before apply.
  • A verified, current backup.
  • A documented rollback procedure (not just a down migration — a time estimate and a smoke test).
  • Log the decision in docs/decisions/.

Phase 7 — Documentation and Handoff

22. Document in docs/data-model.md. Use the template at .claude/templates/data-model.md. Sections: ER diagram (Mermaid), per-entity field tables, relationship list with cardinality and referential action, index plan tied to named queries, sensitive-data classification table, audit/retention rules, and migration strategy summary.

23. Hand off to API design. A complete data model is the input to .claude/skills/api-design/SKILL.md. The data model defines what can be exposed; the API design defines how.


Standards

  • Do use one naming convention across the entire schema (snake_case for SQL is conventional; enforce it without exception). Singular or plural table names — pick one and never mix.
  • Do enforce referential integrity and invariants at the database level for all critical data; application-level enforcement alone is insufficient.
  • Do make every migration reversible and code-reviewed; ship forward + rollback together.
  • Do derive indexes from real, named queries and verify with EXPLAIN/ANALYZE before deploying.
  • Do record created_at / updated_at on all mutable entities using DB-level defaults.
  • Do classify all sensitive fields and specify protection before writing persistence code.
  • Do prefer UUIDv7 or ULID over sequential integer IDs for distributed systems.
  • Do not run destructive migrations (DROP TABLE/COLUMN, narrowing type change, truncate) without explicit human approval and a verified backup — this is a guarded, irreversible action.
  • Do not store secrets, full card numbers (PCI), or unencrypted PII/PHI in plain columns.
  • Do not over-normalize to the point of unusable query complexity (6+ table joins for a common read path is a sign to revisit), nor denormalize without a documented consistency plan.
  • Do not skip the conceptual ER step and jump straight to DDL — the conceptual step catches domain misunderstandings before they solidify.
  • Do not use magic integer codes for status/type columns; use string enums or lookup tables that are self-documenting in queries.

Common mistakes to avoid

  • Modeling tables from UI screens instead of the domain, producing brittle schemas coupled to the current UI design.
  • Missing FK indexes — foreign key columns used in joins without an index cause silent full-table scans at scale. Index every FK.
  • Over-indexing — an index on every column cripples write throughput. Each index must trace to a real query.
  • Nullable everything — when everything is nullable the schema enforces no invariants and bugs accumulate silently in the data.
  • Hard-deleting records that audit or compliance requires retained — add deleted_at; the cost is low and the recovery value is high.
  • Irreversible single-step migrations — renaming or dropping a column in one deploy with no rollback blocks safe recovery.
  • Deferring PII/encryption classification until an audit forces a costly, live-data redesign.
  • Choosing a storage paradigm by familiarity rather than by access patterns — e.g., using a relational table for time-series telemetry, or a document store for data with complex cross-entity transactions.
  • Natural key creep — using mutable user-facing values (email, username, phone) as primary or foreign keys. When the value changes, cascades break.
  • Not testing the down migration — the rollback only matters in an emergency; discovering it is broken then is the worst possible time.

Output format

A completed docs/data-model.md using .claude/templates/data-model.md, containing:

  1. Mermaid erDiagram covering all entities and relationships.
  2. Per-entity field tables: field | type | nullable | constraints | notes.
  3. Relationship/cardinality list with referential actions.
  4. Index plan: each index named, columns listed with order rationale, tied to a named query or use case.
  5. Sensitive-data classification table: column, entity, classification, protection method, retention.
  6. Audit and lifecycle rules (soft-delete strategy, partitioning plan if applicable).
  7. Migration strategy: expand/contract pattern description, rollback approach, and any already-written migration file paths.

Migration files live in the project's migrations/ (or equivalent) directory, each with an up and down, sequentially numbered.

Related checklists

  • .claude/checklists/security.md
  • .claude/checklists/performance.md
  • .claude/checklists/database.md
  • .claude/checklists/production.md

Related agents

  • .claude/agents/core/solution-architect.md
  • .claude/agents/engineering/database-architect.md
  • .claude/agents/quality/security-auditor.md
  • .claude/agents/quality/performance-engineer.md

What ships with it

Read from the repository

Just SKILL.md. No reference files, no scripts.

Keep looking

Skills are one crate of 326,758. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.