data-layer
Skill0 starsChanged 51 days agoMITView on GitHub
Design schemas, write migrations and make queries fast without guessing. Use when the user asks to design a database, model data, write a schema or a migration, add an index, fix a slow query, choose between normalised and denormalised design, handle soft deletes, store money or timestamps, or asks why their database is slow or locked up. Also use before any change to a production table. Reads the query plan instead of guessing at indexes, treats a migration on a large table as a production operation with a lock estimate, enforces invariants in the schema rather than only in application code, and refuses to store money in floating point. Triggers on design a database, data model, schema design, write a migration, add an index, slow query, N+1, normalise, denormalise, soft delete, foreign key, transaction, deadlock, Postgres, MySQL, SQLite, MongoDB.
4 other projects use a version of this.
Adopted by
Most recently taken up by
- ethereum/ethereum-org-websitetheir own version, first seen Oct 8, 2026
- angelgabrieljacintohuayllasco/clipboard-skillstheir own version, first seen Sep 20, 2026
- anipy1/claude-flutter-kittheir own version, first seen Jul 26, 2026
- thetruong1099/android-mvi-base-codetheir own version, first seen Mar 18, 2026
Other versions4 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 4
- ethereum/ethereum-org-website★ 6ksame name
- angelgabrieljacintohuayllasco/clipboard-skills★ 0same name
- anipy1/claude-flutter-kit★ 0same name
- thetruong1099/android-mvi-base-code★ 0same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository57 other files it gives its agents.
- accessibility-auditSkill
- agent-orchestrateSkill
- arch-decideSkill
- auth-implementSkill
- backend-buildSkill
- build-pilotSkill
- business-modelSkill
- career-strategySkill
- codebase-onboardSkill
- code-craftSkill
- code-reviewSkill
- compliance-mapSkill
- content-craftSkill
- cost-controlSkill
- data-analysisSkill
- debug-methodSkill
- deep-researchSkill
- dependency-guardSkill
- design-systemSkill
- devex-toolingSkill
- doc-forgeSkill
- email-deliverSkill
- finance-booksSkill
- frontend-buildSkill
- git-disciplineSkill
- growth-experimentSkill
- human-proseSkill
- i18n-localizeSkill
- incident-responseSkill
- index-fastSkill
- infra-deploySkill
- job-huntSkill
- landing-convertSkill
- launch-planSkill
- llm-app-buildSkill
- llm-visibilitySkill
- memory-keeperSkill
- migration-planSkill
- ml-buildSkill
- mobile-buildSkill
- numbers-checkSkill
- observability-setupSkill
- payments-integrateSkill
- performance-tuningSkill
- pricing-modelSkill
- prompt-forgeSkill
- queue-designSkill
- reality-checkSkill
- refactor-safelySkill
- release-manageSkill
- security-hardeningSkill
- seo-optimizeSkill
- ship-auditSkill
- skill-forgeSkill
- test-strategySkill
- ui-designSkill
- user-researchSkill
The file
Show its rules and text
We split this skill into the rules it gives an agent
15 rules. 0 are common, 15 are distinctive, and 0 are very specific to this project.
0
Common
Most of the 3 edited versions we read keep these.
15
Distinctive
This author's own choices. Worth a look.
0
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 19
If the user has a migration written and wants it applied rather than reviewed, the off switch is saying "just execute" or "stop".
- Distinctive: line 25
Read the existing database and its migration history before proposing a change.
- Distinctive: line 28
Read the migration directory in order.
- Distinctive: line 36
Check how migrations are run and rolled back: the tool, whether down migrations exist and are tested, and whether backfills are batched.
- Distinctive: line 39
When the project has settled none of this, follow the engine's documented conventions, state the identifier and timestamp choices you made, …
- Distinctive: line 45
Never store money in a binary floating point type.
- Distinctive: line 47
Read the query plan before adding an index.
- Distinctive: line 49
Every migration has a tested path back, or a stated reason why it cannot have one and what the recovery is instead.
- Distinctive: line 50
Never run a destructive statement without a transaction and a verified backup.
- Distinctive: line 89
Run the query with the plan output before and after.
- Distinctive: line 97
Look for a sequential scan on a large table, a row estimate far from the actual count, a sort that could have come from an index, and a …
- Distinctive: line 107
Every index slows writes and takes space.
- Distinctive: line 112
Keep transactions short. A transaction held open across a network call to another service is how a connection pool gets exhausted.
- Distinctive: line 121
Never wait for a user inside a transaction.
- Distinctive: line 170
Every intermediate deploy state works with both old and new code.
“Common” is measured: kept by at least 6 in 10 of the 3 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Data layer
The schema outlives the application code that reads it. Decisions here are the most expensive ones in most systems to reverse.
The migration files, query helpers and seed scripts this skill produces follow the code-craft contract,
so a reviewer reads a named migration with its up and down path rather than a wall of statements.
If the user has a migration written and wants it applied rather than reviewed, the off switch is saying "just execute" or "stop". This skill then stops estimating locks and proposing index changes and does what was asked, and it stays off for the rest of the session unless the user asks for a schema review again.
Fit to the project
Read the existing database and its migration history before proposing a change. The schema already encodes decisions that a new table has to respect.
- Read the migration directory in order. The history shows the naming convention for tables and columns, whether the project uses singular or plural table names, how identifiers are typed, and whether soft deletes, timestamps and tenancy columns follow a house pattern. Match what is there.
- Detect the engine and its exact version from the config or the connection string, because lock behaviour, default rewrite rules and concurrent index support differ between versions and between Postgres, MySQL and SQLite. Confirm the version before estimating any migration.
- Capture the real query plan for the query in question against production sized data, not a fresh database with a handful of rows, and read the current indexes on the affected tables before adding one.
- Check how migrations are run and rolled back: the tool, whether down migrations exist and are tested, and whether backfills are batched. New migrations use the same tool and the same reverse path discipline.
When the project has settled none of this, follow the engine's documented conventions, state the identifier and timestamp choices you made, and record them so the next migration matches.
Non-negotiables
- Constraints live in the schema. Not null, unique, foreign keys, and check constraints. Application code has bugs, gets bypassed by scripts, and does not apply to the row someone inserted by hand. The database does not forget.
- Never store money in a binary floating point type. Use a decimal or an integer count of minor units, and store the currency alongside it.
- Store timestamps with a time zone, in UTC, and convert for display. A naive timestamp is a defect waiting for a daylight saving change.
- Read the query plan before adding an index. Guessed indexes cost write throughput and storage while the slow query stays slow.
- Estimate the lock and the duration for any migration against production row counts, not against a development database with two hundred rows.
- Every migration has a tested path back, or a stated reason why it cannot have one and what the recovery is instead.
- Never run a destructive statement without a transaction and a verified backup. This includes ad hoc fixes, which is where most data loss happens.
Procedure
Step 1, model from the queries
Design from how data will be read, not only from how it relates. List the queries the application will run, with their expected frequency and the volume they touch. That list determines the indexes and sometimes the shape.
Normalise first. One fact in one place. Denormalise later against a measured read problem, and when you do, write down what keeps the copies consistent.
Name the invariants. Statements such as an order always has at least one line, or a balance is never negative. Then decide which are enforceable in the schema, and enforce those there.
Step 2, get the primitives right
Pick the narrowest correct type. Text with a length constraint where a length is genuinely bounded, otherwise unbounded text, which is not slower in most engines.
Identifiers: a database generated sequence is fine internally, and anything exposed externally should be opaque. A sortable random identifier gives uniqueness without enumerability and keeps index locality, which fully random identifiers lose.
Enumerations: a lookup table with a foreign key survives change better than a database enum type, which is awkward to alter, and better than a free text column, which drifts.
Nullable columns: decide deliberately. Null means unknown, and using it to mean zero, empty or false produces queries that are wrong in ways nobody notices.
JSON columns are for genuinely variable data you never filter across. The failure is querying inside them later at volume.
Patterns for common shapes such as history, soft delete, multi tenancy, hierarchies, audit trails and
scheduling are in references/patterns.md.
Step 3, index from the plan
Run the query with the plan output before and after. Report both.
EXPLAIN (ANALYZE, BUFFERS) SELECT ...; -- Postgres
EXPLAIN ANALYZE SELECT ...; -- MySQL 8+
EXPLAIN QUERY PLAN SELECT ...; -- SQLiteLook for a sequential scan on a large table, a row estimate far from the actual count, a sort that could have come from an index, and a nested loop over many rows.
Composite index column order follows equality first, then range, then the ordering column. A composite index serves queries that use a prefix of its columns, so three single column indexes are not equivalent to one composite.
A covering index that includes the selected columns avoids reading the table at all, which is the largest available win on a hot read path.
Every index slows writes and takes space. Find and drop the unused ones, since most schemas accumulate them.
Step 4, transactions and concurrency
Keep transactions short. A transaction held open across a network call to another service is how a connection pool gets exhausted.
Know the isolation level you are running at and what it permits. Read committed, the common default, allows the read then write race, so protect the write with a conditional update, a version column, or a lock.
Take locks in a consistent order everywhere.
Never wait for a user inside a transaction.
Handle the unique constraint violation rather than checking existence first and inserting after, which races between the check and the insert.
Step 5, migrations as production operations
Separate schema change from data change from code change, and deploy in an order where every intermediate state works. Old code must tolerate the new schema, because both run at once during a deploy.
The safe sequence for a rename: add the new column, write to both, backfill in batches, move reads, stop writing the old one, drop it later. Renaming in one step breaks whatever is still running.
Adding a nullable column without a default is usually cheap. Adding one with a default rewrites the table in older engines, so check the behaviour of the specific version.
Adding an index on a large table locks writes unless built concurrently, which is a different statement and cannot run inside a transaction.
Backfill in batches with a pause, and make the backfill resumable. A single statement touching ten million rows holds locks and cannot be interrupted safely.
Estimate before running: count the rows, check the table size, and state the expected duration and what blocks during it.
The lock behaviour of common operations, the expand and contract sequence for renames and type changes, and
a worked batched backfill are in references/migrations.md.
Step 6, operational basics
Backups that have been restored at least once. An untested backup is a hope.
Point in time recovery configured if the data cannot be reconstructed.
Connection pooling sized against the database's actual limit, not the application's optimism.
Slow query logging on, and someone reading it.
Retention decided per table, including for audit and log tables, which grow without bound and are usually forgotten.
Self-audit
- Constraints in the schema, not only in code.
- Money in decimal or minor units, with currency.
- Timestamps stored with zone in UTC.
- Query plan captured before and after each index, and included in the output.
- Migration lock and duration estimated against production row counts.
- Reverse path tested, or its absence explained.
- Every intermediate deploy state works with both old and new code.
- Backfills batched and resumable.
- Retention decided for anything append only.
Honest limits
This skill designs the schema, the indexes and the migration path. It does not build the request handlers or
the transaction orchestration in the application above it, which belong to backend-build, and it does not
decide whether a datastore should exist at all or be split from another, which is an architecture question
arch-decide owns. The migration and query code it emits is held to the code-craft contract for structure
and comments.
The lock and rewrite behaviour in references/migrations.md describes common engines and versions in general
terms, and the exact behaviour differs by engine and release, so confirm against the version in use before
running a migration. The lock and duration estimates come from reading the query plan and the row count, not
from a formula, and they are estimates rather than guarantees on a loaded production system.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

