DEV Community

Alex Spinov
Alex Spinov

Posted on

Drizzle ORM Has a Free API — SQL That TypeScript Developers Actually Love

Drizzle ORM is a TypeScript ORM that gives you full SQL power with type safety. Unlike Prisma, Drizzle generates SQL you can read, runs queries you can predict, and adds zero runtime overhead.

Why Drizzle?

  • SQL-like syntax — if you know SQL, you know Drizzle
  • Zero overhead — thin typed layer over SQL, no query engine
  • Serverless-ready — works with D1, Turso, Neon, PlanetScale
  • Drizzle Kit — migrations, studio, push — all built-in

Quick Start

npm install drizzle-orm postgres
npm install -D drizzle-kit
Enter fullscreen mode Exit fullscreen mode
// schema.ts
import { pgTable, serial, text, integer, timestamp } from 'drizzle-orm/pg-core';

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

export const posts = pgTable('posts', {
  id: serial('id').primaryKey(),
  title: text('title').notNull(),
  content: text('content'),
  authorId: integer('author_id').references(() => users.id),
});
Enter fullscreen mode Exit fullscreen mode

CRUD Operations

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

const client = postgres('postgresql://localhost:5432/mydb');
const db = drizzle(client);

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

// Select
const allUsers = await db.select().from(users);
const alice = await db.select().from(users).where(eq(users.email, 'alice@example.com'));

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

// Delete
await db.delete(users).where(eq(users.id, 1));
Enter fullscreen mode Exit fullscreen mode

Joins

const usersWithPosts = await db
  .select({
    userName: users.name,
    postTitle: posts.title,
  })
  .from(users)
  .leftJoin(posts, eq(users.id, posts.authorId))
  .where(like(users.name, '%Ali%'))
  .orderBy(desc(posts.createdAt))
  .limit(10);
Enter fullscreen mode Exit fullscreen mode

Relations (Query API)

import { relations } from 'drizzle-orm';

export const usersRelations = relations(users, ({ many }) => ({
  posts: many(posts),
}));

export const postsRelations = relations(posts, ({ one }) => ({
  author: one(users, {
    fields: [posts.authorId],
    references: [users.id],
  }),
}));

// Query with relations
const result = await db.query.users.findMany({
  with: {
    posts: true,
  },
  where: eq(users.age, 30),
});
Enter fullscreen mode Exit fullscreen mode

Migrations

// drizzle.config.ts
export default {
  schema: './schema.ts',
  out: './drizzle',
  dialect: 'postgresql',
  dbCredentials: {
    url: 'postgresql://localhost:5432/mydb',
  },
};
Enter fullscreen mode Exit fullscreen mode
npx drizzle-kit generate  # Generate migration SQL
npx drizzle-kit migrate   # Apply migrations
npx drizzle-kit push      # Push schema directly
npx drizzle-kit studio    # Visual database browser
Enter fullscreen mode Exit fullscreen mode

Need to store scraped data? Check out my Apify actors for web scraping + database pipeline, or email spinov001@gmail.com for custom data solutions.

Drizzle or Prisma — which ORM do you use? Share below!

Top comments (0)