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
{
"context": "Tests whether the agent proactively applies Drizzle schema best practices: explicit indexes on FK columns (Drizzle does NOT auto-index), indexes on filtered columns, references with onDelete, money as integer cents, text with enum option for status fields, createdAt/updatedAt on ALL tables, relations() for query API, foreign_keys pragma for SQLite, passing schema to drizzle(), and proper schema file location. The task describes only business requirements.",
"type": "weighted_checklist",
"checklist": [
{
"name": "Indexes on FK columns",
"description": "Every foreign key column (e.g., eventId on ticket_types, eventId and ticketTypeId on purchases) has an explicit index() defined in the table's third-argument callback using index('name').on(table.column)",
"max_score": 12
},
{
"name": "Indexes on filtered columns",
"description": "Columns used for filtering (event status, event date, purchase status) have indexes defined",
"max_score": 8
},
{
"name": "References with onDelete",
"description": "All foreign key .references() calls include an explicit onDelete action (cascade, restrict, or set null) -- not bare references() without onDelete",
"max_score": 10
},
{
"name": "Money as integer cents",
"description": "Ticket prices and any monetary values are stored as integer representing cents (e.g., priceCents), not real/float/text",
"max_score": 10
},
{
"name": "Enum via text with enum option",
"description": "Event status and purchase status fields use text('col', { enum: ['value1', 'value2'] }) pattern, not plain text()",
"max_score": 8
},
{
"name": "createdAt on all tables",
"description": "Every table has a createdAt column with a SQL default expression (sql`(datetime('now'))` for SQLite)",
"max_score": 7
},
{
"name": "updatedAt on all mutable tables",
"description": "All tables that can be updated (events, purchases, and ticket_types at minimum) include an updatedAt column -- not just the main entity table",
"max_score": 8
},
{
"name": "Relations defined",
"description": "relations() objects are defined for tables with foreign keys, using one() and many() to enable the query API with nested eager loading",
"max_score": 10
},
{
"name": "Schema passed to drizzle",
"description": "The drizzle() call in db.ts passes { schema } (or equivalent) as the second argument to enable the query API",
"max_score": 7
},
{
"name": "SQLite foreign_keys pragma",
"description": "The SQLite connection setup enables the foreign_keys pragma (sqlite.pragma('foreign_keys = ON') or equivalent) since SQLite has FK enforcement OFF by default",
"max_score": 8
},
{
"name": "SQLite WAL mode",
"description": "The SQLite connection enables WAL journal mode for concurrent read access",
"max_score": 5
},
{
"name": "notNull on required columns",
"description": "Required columns (name, date, price, status, quantity) are marked with .notNull()",
"max_score": 7
}
]
}