Does Supabase Work With Drizzle ORM?
Yes, Drizzle ORM works excellently with Supabase as your PostgreSQL database provider with full type safety and modern DX.
Quick Facts
How Supabase Works With Drizzle ORM
Drizzle ORM is a perfect fit for Supabase because both prioritize PostgreSQL as a first-class citizen. Supabase provides a managed PostgreSQL instance with connection pooling via PgBouncer, and Drizzle connects directly via the standard postgres/pg driver or the lightweight postgres.js library. You define your schema in TypeScript with Drizzle, generate migrations, and push them to your Supabase database—no SQL needed unless you want it. The developer experience is particularly smooth: Drizzle's schema definitions double as your type definitions, eliminating the need for separate type generation. Real-time features in Supabase (like Postgres LISTEN/NOTIFY) work transparently underneath Drizzle. The main architectural consideration is connection pooling—Supabase's PgBouncer requires transaction mode for certain operations, which Drizzle handles correctly out of the box. You can also leverage Supabase's native features like RLS policies and Auth directly, since Drizzle just abstracts the query layer. This combination is increasingly popular in modern full-stack TypeScript applications because it provides compile-time safety without sacrificing flexibility.
Best Use Cases
Quick Setup
npm install drizzle-orm postgres dotenv && npm install -D drizzle-kitimport { drizzle } from 'drizzle-orm/postgres-js';
import postgres from 'postgres';
import { pgTable, serial, text, timestamp } from 'drizzle-orm/pg-core';
const client = postgres(process.env.DATABASE_URL!);
const db = drizzle(client);
export const users = pgTable('users', {
id: serial('id').primaryKey(),
email: text('email').notNull().unique(),
createdAt: timestamp('created_at').defaultNow(),
});
// Query example
const allUsers = await db.select().from(users);
const newUser = await db.insert(users).values({
email: 'user@example.com',
}).returning();Known Issues & Gotchas
PgBouncer transaction mode can cause issues with long-running transactions or certain Drizzle patterns
Fix: Use session mode for connections that need explicit transactions, or break long operations into smaller queries. Supabase supports both modes on the connection string.
Drizzle's default schema inference doesn't automatically recognize Supabase's built-in tables (auth.users, storage.objects)
Fix: Reference these tables manually in your schema definitions if you need to query them, or use raw SQL for schema introspection.
RLS policies are enforced at the database level, but Drizzle doesn't validate them at query time
Fix: Test RLS policies separately and ensure your app's service role vs. user role is correct when executing queries through Drizzle.
Alternatives
- •Prisma + Supabase (more opinionated, larger ecosystem)
- •TypeORM + Supabase (more traditional ORM, heavier footprint)
- •Raw postgres.js/node-postgres + Supabase (maximum control, no ORM)
Resources
Related Compatibility Guides
Explore more compatibility guides