Skip to content

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

{
  "drizzle-orm": "^0.45.1",
  "drizzle-kit": "^0.31.9"
}

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

  1. PostgreSQL is SSOT — the database is the single source of truth. Filesystem is optional audit trail only.
  2. Schema modules by domain — never one monolithic schema file.
  3. snake_case in SQL, camelCase in TypeScript — Drizzle handles the mapping via column name strings.
  4. All timestamps use withTimezone: true — EU data sovereignty requires timezone-aware storage.
  5. UUIDs for entity IDs — except agent IDs which use human-readable text (e.g., 'urszula', 'floris').
  6. Every table gets createdAt and updatedAt with defaultNow().
  7. 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