CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl-labs/drizzle-best-practices

Drizzle ORM patterns -- schema definition, indexes, relations, migrations, transactions, upserts, prepared statements, and connection setup

96

1.60x
Quality

96%

Does it follow best practices?

Impact

98%

1.60x

Average score across 5 eval scenarios

SecuritybySnyk

Passed

No known issues

Overview
Quality
Evals
Security
Files

drizzle-schema.jsonverifiers/

{
  "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"
    }
  ]
}

tile.json