Skip to content

Drizzle ORM

This document describes how we use Drizzle ORM for database operations in the Registration Backend service with examples.

Overview

We use Drizzle ORM as our database layer. Drizzle provides type-safe database queries with minimal abstraction over SQL.

Database Setup

Local Development

Start PostgreSQL with Docker:

docker compose up -d

Copy the example environment file and configure it:

cp .env.example .env

Stage and Production

In production and stage, the database runs on AWS Aurora (PostgreSQL).

Schema Definition

Schemas are defined in TypeScript files under app/database/. See app/database/schemas for example.

Database Connection

Get the database client using getDB() from app/database/db.server.ts:

import { getDb } from "~/database/db.server.js";

const db = await getDb();
const users = await db.select().from(users);

Migrations

Generate Migration

After changing your schema, generate a migration:

pnpm run db:generate

This creates a SQL file in packages/migrations/drizzle/. Review the generated SQL before applying.

Apply Migration

Apply pending migrations:

pnpm run db:migrate

Seed Database

Populate the database with example data for local development:

pnpm run db:seed

View Database

Open Drizzle Studio to browse your database:

pnpm run db:studio

Querying

See Drizzle docs for query examples.

Type Safety

Types are automatically inferred from schema definitions:

import type { InferSelectModel } from "drizzle-orm";
import { users } from "~/database/schemas/users";

type User = InferSelectModel<typeof usersTableExample>;