Isaac.

Drizzle ORM Getting Started

Build type-safe database queries with Drizzle ORM.

By EMEPublished: February 20, 2025
drizzleormtypescriptdatabasetype-safe

A Simple Analogy

Drizzle ORM is like a type-safe translator. It converts TypeScript types into SQL queries.


Why Drizzle?

  • Type-safe: Full TypeScript support
  • Lightweight: Minimal overhead
  • SQL-like: Familiar syntax
  • Multiple DBs: PostgreSQL, MySQL, SQLite
  • Migrations: Built-in migration tools

Setup

# Install
npm install drizzle-orm drizzle-kit postgres
npm install -D @types/node

# Create schema file
touch src/schema.ts
touch drizzle.config.ts

Define Schema

// src/schema.ts
import { pgTable, serial, varchar, integer, timestamp } from 'drizzle-orm/pg-core';

export const users = pgTable('users', {
  id: serial('id').primaryKey(),
  name: varchar('name', { length: 256 }).notNull(),
  email: varchar('email', { length: 256 }).notNull().unique(),
  age: integer('age'),
  createdAt: timestamp('created_at').defaultNow().notNull(),
});

export const posts = pgTable('posts', {
  id: serial('id').primaryKey(),
  authorId: integer('author_id').references(() => users.id),
  title: varchar('title', { length: 256 }).notNull(),
  content: varchar('content'),
  createdAt: timestamp('created_at').defaultNow().notNull(),
});

Configuration

// drizzle.config.ts
import { Config } from 'drizzle-kit';

const config: Config = {
  schema: './src/schema.ts',
  out: './drizzle',
  driver: 'pg',
  dbCredentials: {
    connectionString: process.env.DATABASE_URL,
  },
};

export default config;

Queries

import { drizzle } from 'drizzle-orm/node-postgres';
import { eq, like } from 'drizzle-orm';
import { users, posts } from './schema';

const db = drizzle(process.env.DATABASE_URL);

// Select all users
const allUsers = await db.select().from(users);

// Select with filter
const user = await db.select()
  .from(users)
  .where(eq(users.id, 1));

// Filter by string pattern
const matches = await db.select()
  .from(users)
  .where(like(users.email, '%@example.com'));

// Join tables
const userPosts = await db.select()
  .from(users)
  .innerJoin(posts, eq(users.id, posts.authorId))
  .where(eq(users.id, 1));

Insert and Update

// Insert user
await db.insert(users).values({
  name: 'Alice',
  email: 'alice@example.com',
  age: 30,
});

// Update user
await db.update(users)
  .set({ age: 31 })
  .where(eq(users.id, 1));

// Delete user
await db.delete(users)
  .where(eq(users.id, 1));

Best Practices

  1. Migrations: Use drizzle-kit for schema changes
  2. Transactions: Batch operations
  3. Type safety: Let TypeScript catch errors
  4. Indexes: Add for frequently queried columns
  5. Validation: Validate at application level

Related Concepts

  • Prisma ORM
  • TypeORM
  • Sequelize
  • Database migrations

Summary

Drizzle provides type-safe database queries in TypeScript. Define schemas, run migrations, and write SQL-like queries.