Drizzle — Overview¶
OWNER: urszula, maxim ALSO_USED_BY: boris, floris, hugo, jasper, marco, stef, arjan LAST_VERIFIED: 2026-03-26 GE_STACK_VERSION: drizzle-orm 0.45.x, drizzle-kit 0.31.x
Overview¶
Drizzle ORM is the ONLY ORM permitted in GE projects. Every client project, internal tool, and admin surface uses Drizzle for database access. No exceptions. No Prisma. No TypeORM. No Knex.
Agents writing database code MUST read this page and the related topic pages before generating any schema, query, or migration code.
Why Drizzle¶
CHECK: Agent is selecting a database access layer.
IF: The project uses PostgreSQL (which is always).
THEN: Use drizzle-orm with drizzle-kit. No alternatives.
Decision rationale (decided 2025-Q4, reconfirmed 2026-Q1):
| Criterion | Drizzle | Prisma | TypeORM |
|---|---|---|---|
| TypeScript inference | Full — zero codegen | Requires prisma generate |
Decorator-based, weak inference |
| SQL proximity | 1:1 SQL mental model | Abstracted, hides SQL | Abstracted, hides SQL |
| Migration control | SQL files, human-readable | Opaque migration engine | Opaque migration engine |
| Bundle size | ~50KB | ~2MB+ engine binary | ~800KB |
| Multi-tenant RLS | Native SQL passthrough | Limited | Limited |
| Serverless compat | Excellent (no engine binary) | Cold start penalty | Cold start penalty |
GE Version Pinning¶
CHECK: Agent is adding drizzle to a new project. IF: Version differs from above. THEN: Use the pinned version unless Joshua (Innovation) has approved an upgrade.
GE Project Structure¶
Every GE project follows this Drizzle layout:
project-root/
drizzle/
schema.ts # Re-exports from schema/index.ts
schema/
index.ts # Barrel export of all domain modules
enums.ts # All pgEnum definitions
{domain}.ts # Domain-specific tables (agents, clients, billing...)
migrations/
0000_*.sql # Sequential numbered migrations
meta/ # drizzle-kit metadata (auto-generated)
drizzle.config.ts # drizzle-kit configuration
lib/
db/
index.ts # Database connection + drizzle instance
CHECK: Agent is creating a new schema file.
IF: The table belongs to an existing domain (e.g., billing, auth, agents).
THEN: Add it to the existing drizzle/schema/{domain}.ts file.
IF: The table starts a new domain.
THEN: Create a new drizzle/schema/{domain}.ts and add the export to drizzle/schema/index.ts.
Connection Setup¶
The standard GE connection pattern uses postgres (postgres.js) driver:
// lib/db/index.ts
import { drizzle } from 'drizzle-orm/postgres-js';
import postgres from 'postgres';
import * as schema from '@/drizzle/schema';
const connectionString = process.env.DATABASE_URL!;
const client = postgres(connectionString);
export const db = drizzle(client, { schema });
export { schema };
ANTI_PATTERN: Creating multiple postgres() clients in different files.
FIX: Import db from lib/db/index.ts everywhere. One client per process.
ANTI_PATTERN: Hardcoding connection strings.
FIX: Always read from DATABASE_URL environment variable.
Drizzle Config¶
// drizzle.config.ts
import { defineConfig } from 'drizzle-kit';
export default defineConfig({
schema: './drizzle/schema.ts',
out: './drizzle/migrations',
dialect: 'postgresql',
dbCredentials: {
url: process.env.DATABASE_URL || 'postgresql://localhost:5432/admin_ui',
},
});
GE-Specific Conventions¶
- PostgreSQL is SSOT — the database is the single source of truth. Filesystem is optional audit trail only.
- Schema modules by domain — never one monolithic schema file.
- snake_case in SQL, camelCase in TypeScript — Drizzle handles the mapping via column name strings.
- All timestamps use
withTimezone: true— EU data sovereignty requires timezone-aware storage. - UUIDs for entity IDs — except agent IDs which use human-readable text
(e.g.,
'urszula','floris'). - Every table gets
createdAtandupdatedAtwithdefaultNow(). - Indexes are defined inline in the table's third argument, not separately.
Cross-References¶
READ_ALSO: wiki/docs/stack/drizzle/schema-design.md READ_ALSO: wiki/docs/stack/drizzle/queries.md READ_ALSO: wiki/docs/stack/drizzle/migrations.md READ_ALSO: wiki/docs/stack/drizzle/pitfalls.md READ_ALSO: wiki/docs/stack/drizzle/checklist.md READ_ALSO: wiki/docs/stack/postgresql/index.md READ_ALSO: wiki/docs/stack/postgresql/multi-tenant.md READ_ALSO: wiki/docs/development/standards/naming.md