Drizzle ORM patterns -- schema definition, indexes, relations, migrations, transactions, upserts, prepared statements, and connection setup
96
96%
Does it follow best practices?
Impact
98%
1.60xAverage score across 5 eval scenarios
Passed
No known issues
{
"instruction": "Define Drizzle schema with proper types, indexes, references, timestamps, and relations",
"relevant_when": "Agent defines Drizzle ORM table schemas or database models",
"context": "Drizzle does NOT auto-index foreign keys. Schemas must have explicit index() on every FK column and filtered columns, references() with onDelete, integer for money (never real/float), text with enum option for status fields, createdAt/updatedAt on ALL tables (including join tables), SQL expression defaults for timestamps, relations() for every table with FKs, and schema files in src/db/schema.ts.",
"sources": [
{
"type": "file",
"filename": "skills/drizzle-best-practices/SKILL.md",
"tile": "tessl-labs/drizzle-best-practices@0.2.0"
}
],
"checklist": [
{
"name": "indexes-on-fk-columns",
"rule": "Agent creates explicit index() on every foreign key column using index('name').on(table.column) in the table's third-argument callback. Drizzle does NOT auto-index foreign keys.",
"relevant_when": "Agent defines Drizzle table schemas with foreign key references"
},
{
"name": "indexes-on-filtered-columns",
"rule": "Agent creates index() on columns used for filtering or sorting (status, category, createdAt, etc.)",
"relevant_when": "Agent defines Drizzle table schemas with columns that will be queried by"
},
{
"name": "references-with-ondelete",
"rule": "Agent uses .references(() => table.col, { onDelete: 'cascade' }) or other explicit onDelete action on every foreign key, not bare .references() without onDelete",
"relevant_when": "Agent defines foreign key relationships in Drizzle schema"
},
{
"name": "money-as-integer-cents",
"rule": "Money/price/cost fields use integer type storing cents (e.g., priceCents, totalCents), never real or float which cause rounding errors",
"relevant_when": "Agent defines fields for monetary values in Drizzle schema"
},
{
"name": "enum-via-text-option",
"rule": "Status/category fields with finite values use text('col', { enum: ['value1', 'value2'] }) for TypeScript type narrowing",
"relevant_when": "Agent defines status, type, or category fields with known values"
},
{
"name": "created-at-on-all-tables",
"rule": "Agent includes createdAt column with SQL default expression (sql`(datetime('now'))` for SQLite or .defaultNow() for PostgreSQL) on every table",
"relevant_when": "Agent defines Drizzle table schemas"
},
{
"name": "updated-at-on-all-tables",
"rule": "Agent includes updatedAt column on ALL mutable tables, including join/pivot tables, not just the main entity tables",
"relevant_when": "Agent defines Drizzle table schemas"
},
{
"name": "relations-defined",
"rule": "Agent defines relations() objects for tables with foreign keys, enabling the query API (db.query.table.findMany with 'with' option)",
"relevant_when": "Agent defines Drizzle schemas with multiple related tables"
},
{
"name": "schema-file-location",
"rule": "Schema is defined in src/db/schema.ts (or src/db/schema/ directory for large projects)",
"relevant_when": "Agent creates Drizzle schema files"
},
{
"name": "notnull-on-required-columns",
"rule": "Required columns are marked with .notNull()",
"relevant_when": "Agent defines Drizzle table columns"
}
]
}