TypeScript ORM for SQL databases with type-safe queries, schema definitions, and support for PostgreSQL, MySQL, SQLite, and more.
Complete reference for all Drizzle ORM database drivers, including PostgreSQL, MySQL, SQLite, SingleStore, and GEL drivers, plus integration adapters.
Drizzle ORM supports 20+ database drivers across multiple database engines. Each driver provides the drizzle() function to create a database instance with full type-safety and ORM capabilities.
Node.js PostgreSQL driver using the official pg package.
npm install drizzle-orm pg
npm install -D @types/pgimport { drizzle } from 'drizzle-orm/node-postgres';
import { Pool } from 'pg';function drizzle<TSchema extends Record<string, unknown> = Record<string, never>>(
client: Pool | PoolClient | Client | string,
config?: DrizzleConfig<TSchema>
): NodePgDatabase<TSchema> & { $client: Pool | Client };
// Alternative config-based signature
function drizzle<TSchema>(
config: DrizzleConfig<TSchema> & {
client?: Pool | PoolClient | Client;
connection?: string | PoolConfig;
}
): NodePgDatabase<TSchema>;interface DrizzleConfig<TSchema> {
// Schema for relational queries
schema?: TSchema;
// Logger configuration
logger?: Logger | boolean;
// Automatic column name casing conversion
casing?: 'snake_case' | 'camelCase';
// Cache instance for query result caching
cache?: Cache;
}
// From pg package
interface PoolConfig {
host?: string;
port?: number;
database?: string;
user?: string;
password?: string;
connectionString?: string;
max?: number;
idleTimeoutMillis?: number;
connectionTimeoutMillis?: number;
// ... more pg options
}import { drizzle } from 'drizzle-orm/node-postgres';
import { Pool } from 'pg';
import * as schema from './schema';
// Using Pool instance
const pool = new Pool({
connectionString: process.env.DATABASE_URL,
});
const db = drizzle(pool, { schema });
// Using connection string
const db2 = drizzle(process.env.DATABASE_URL, { schema });
// Using config object
const db3 = drizzle({
connection: {
host: 'localhost',
port: 5432,
user: 'postgres',
password: 'password',
database: 'mydb',
},
schema,
logger: true,
});
// Query examples
const users = await db.select().from(schema.users);
const user = await db.query.users.findFirst({
where: (users, { eq }) => eq(users.id, 1),
});import { migrate } from 'drizzle-orm/node-postgres/migrator';
await migrate(db, {
migrationsFolder: './drizzle',
migrationsTable: 'migrations',
migrationsSchema: 'public',
});PoolwithReplicas()High-performance PostgreSQL driver using postgres (postgres.js).
npm install drizzle-orm postgresimport { drizzle } from 'drizzle-orm/postgres-js';
import postgres from 'postgres';function drizzle<TSchema extends Record<string, unknown> = Record<string, never>>(
client: Sql | string,
config?: DrizzleConfig<TSchema>
): PostgresJsDatabase<TSchema> & { $client: Sql };
// Alternative config-based signature
function drizzle<TSchema>(
config: DrizzleConfig<TSchema> & {
client?: Sql;
connection?: string | ({ url?: string } & Options);
}
): PostgresJsDatabase<TSchema>;import { drizzle } from 'drizzle-orm/postgres-js';
import postgres from 'postgres';
import * as schema from './schema';
// Using postgres client
const client = postgres(process.env.DATABASE_URL);
const db = drizzle(client, { schema });
// Using connection string
const db2 = drizzle(process.env.DATABASE_URL, { schema });
// Using config with options
const db3 = drizzle({
connection: {
url: process.env.DATABASE_URL,
max: 10,
idle_timeout: 20,
connect_timeout: 10,
},
schema,
logger: true,
});
// Query
const users = await db.select().from(schema.users);import { migrate } from 'drizzle-orm/postgres-js/migrator';
await migrate(db, {
migrationsFolder: './drizzle',
});Serverless PostgreSQL driver for Neon with WebSocket support.
npm install drizzle-orm @neondatabase/serverlessimport { drizzle } from 'drizzle-orm/neon-serverless';
import { Pool } from '@neondatabase/serverless';function drizzle<TSchema extends Record<string, unknown> = Record<string, never>>(
client: Pool | Client | string,
config?: DrizzleConfig<TSchema>
): NeonDatabase<TSchema> & { $client: Pool | Client };
// Config-based with WebSocket support
function drizzle<TSchema>(
config: DrizzleConfig<TSchema> & {
client?: Pool | Client;
connection?: string | PoolConfig;
ws?: any; // WebSocket constructor
}
): NeonDatabase<TSchema>;import { drizzle } from 'drizzle-orm/neon-serverless';
import { Pool } from '@neondatabase/serverless';
import * as schema from './schema';
// Using Pool
const pool = new Pool({
connectionString: process.env.DATABASE_URL,
});
const db = drizzle(pool, { schema });
// For serverless environments (Vercel, Cloudflare Workers)
import { neonConfig } from '@neondatabase/serverless';
import ws from 'ws';
neonConfig.webSocketConstructor = ws;
const db2 = drizzle({
connection: process.env.DATABASE_URL,
ws,
schema,
});
// Query
const users = await db.select().from(schema.users);import { migrate } from 'drizzle-orm/neon-serverless/migrator';
await migrate(db, {
migrationsFolder: './drizzle',
});HTTP-based serverless driver for Neon (no WebSocket required).
npm install drizzle-orm @neondatabase/serverlessimport { drizzle } from 'drizzle-orm/neon-http';
import { neon } from '@neondatabase/serverless';function drizzle<TSchema extends Record<string, unknown> = Record<string, never>>(
client: NeonQueryFunction | string,
config?: DrizzleConfig<TSchema>
): NeonHttpDatabase<TSchema> & { $client: NeonQueryFunction };
// Config-based
function drizzle<TSchema>(
config: DrizzleConfig<TSchema> & {
client?: NeonQueryFunction;
connection?: string | ({ connectionString: string } & HTTPTransactionOptions);
}
): NeonHttpDatabase<TSchema>;import { drizzle } from 'drizzle-orm/neon-http';
import { neon } from '@neondatabase/serverless';
import * as schema from './schema';
// Using neon client
const sql = neon(process.env.DATABASE_URL);
const db = drizzle(sql, { schema });
// Using connection string
const db2 = drizzle(process.env.DATABASE_URL, { schema });
// With HTTP options
const db3 = drizzle({
connection: {
connectionString: process.env.DATABASE_URL,
arrayMode: false,
fullResults: false,
},
schema,
});
// Query
const users = await db.select().from(schema.users);
// With auth token (for row-level security)
const protectedUsers = await db
.$withAuth('user-token-123')
.select()
.from(schema.users);const [users, posts] = await db.batch([
db.select().from(schema.users),
db.select().from(schema.posts),
]);import { migrate } from 'drizzle-orm/neon-http/migrator';
await migrate(db, {
migrationsFolder: './drizzle',
});Vercel's PostgreSQL driver built on postgres.js.
npm install drizzle-orm @vercel/postgresimport { drizzle } from 'drizzle-orm/vercel-postgres';
import { sql } from '@vercel/postgres';function drizzle<TSchema extends Record<string, unknown> = Record<string, never>>(
client?: VercelPgClient,
config?: DrizzleConfig<TSchema>
): VercelPgDatabase<TSchema> & { $client: VercelPgClient };
// Config-based
function drizzle<TSchema>(
config: DrizzleConfig<TSchema> & {
client?: VercelPgClient;
}
): VercelPgDatabase<TSchema>;import { drizzle } from 'drizzle-orm/vercel-postgres';
import { sql } from '@vercel/postgres';
import * as schema from './schema';
// Uses environment variables automatically
// POSTGRES_URL or POSTGRES_URL_NON_POOLING
const db = drizzle(sql, { schema });
// Or without client (uses default)
const db2 = drizzle({ schema });
// Query
const users = await db.select().from(schema.users);import { migrate } from 'drizzle-orm/vercel-postgres/migrator';
await migrate(db, {
migrationsFolder: './drizzle',
});Serverless PostgreSQL/MySQL driver using AWS RDS Data API.
npm install drizzle-orm @aws-sdk/client-rds-dataimport { drizzle } from 'drizzle-orm/aws-data-api/pg';
import { RDSDataClient } from '@aws-sdk/client-rds-data';function drizzle<TSchema extends Record<string, unknown> = Record<string, never>>(
client: RDSDataClient,
config: DrizzleAwsDataApiPgConfig<TSchema>
): AwsDataApiPgDatabase<TSchema> & { $client: RDSDataClient };
interface DrizzleAwsDataApiPgConfig<TSchema> extends DrizzleConfig<TSchema> {
database: string; // Database name
resourceArn: string; // RDS cluster ARN
secretArn: string; // Secrets Manager secret ARN
}import { drizzle } from 'drizzle-orm/aws-data-api/pg';
import { RDSDataClient } from '@aws-sdk/client-rds-data';
import * as schema from './schema';
// Using RDS Data Client
const rdsClient = new RDSDataClient({
region: 'us-east-1',
credentials: {
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
},
});
const db = drizzle(rdsClient, {
database: 'mydb',
resourceArn: process.env.RDS_RESOURCE_ARN,
secretArn: process.env.RDS_SECRET_ARN,
schema,
logger: true,
});
// Using config object
const db2 = drizzle({
connection: {
region: 'us-east-1',
credentials: { /* ... */ },
database: 'mydb',
resourceArn: process.env.RDS_RESOURCE_ARN,
secretArn: process.env.RDS_SECRET_ARN,
},
schema,
});
// Query
const users = await db.select().from(schema.users);import { migrate } from 'drizzle-orm/aws-data-api/pg/migrator';
await migrate(db, {
migrationsFolder: './drizzle',
});Embedded WASM PostgreSQL for Node.js and browsers.
npm install drizzle-orm @electric-sql/pgliteimport { drizzle } from 'drizzle-orm/pglite';
import { PGlite } from '@electric-sql/pglite';function drizzle<TSchema extends Record<string, unknown> = Record<string, never>>(
client?: PGlite | string,
config?: DrizzleConfig<TSchema>
): PgliteDatabase<TSchema> & { $client: PGlite };
// Config-based
function drizzle<TSchema>(
config: DrizzleConfig<TSchema> & {
client?: PGlite;
connection?: string | (PGliteOptions & { dataDir?: string });
}
): PgliteDatabase<TSchema>;import { drizzle } from 'drizzle-orm/pglite';
import { PGlite } from '@electric-sql/pglite';
import * as schema from './schema';
// In-memory database
const client = new PGlite();
const db = drizzle(client, { schema });
// Persistent database (Node.js)
const db2 = drizzle('./data/mydb', { schema });
// With options
const db3 = drizzle({
connection: {
dataDir: './data/mydb',
debug: true,
},
schema,
});
// Browser (in-memory)
const db4 = drizzle({ schema });
// Query
const users = await db.select().from(schema.users);import { migrate } from 'drizzle-orm/pglite/migrator';
await migrate(db, {
migrationsFolder: './drizzle',
});Custom proxy driver for remote PostgreSQL execution.
npm install drizzle-ormimport { drizzle } from 'drizzle-orm/pg-proxy';type RemoteCallback = (
sql: string,
params: any[],
method: 'all' | 'execute',
typings?: any[]
) => Promise<{ rows: any[] }>;
function drizzle<TSchema extends Record<string, unknown> = Record<string, never>>(
callback: RemoteCallback,
config?: DrizzleConfig<TSchema>
): PgRemoteDatabase<TSchema>;import { drizzle } from 'drizzle-orm/pg-proxy';
import * as schema from './schema';
// Define proxy callback
const callback: RemoteCallback = async (sql, params, method) => {
try {
const response = await fetch('https://api.example.com/sql', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ sql, params, method }),
});
const { rows } = await response.json();
return { rows };
} catch (error) {
console.error('Query failed:', error);
return { rows: [] };
}
};
const db = drizzle(callback, { schema });
// Query (proxied to remote server)
const users = await db.select().from(schema.users);import { migrate } from 'drizzle-orm/pg-proxy/migrator';
await migrate(db, {
migrationsFolder: './drizzle',
});HTTP driver for Xata's PostgreSQL service.
npm install drizzle-orm @xata.io/clientimport { drizzle } from 'drizzle-orm/xata-http';
import { getXataClient } from './xata'; // Generated Xata clientfunction drizzle<TSchema extends Record<string, unknown> = Record<string, never>>(
client: XataHttpClient,
config?: DrizzleConfig<TSchema>
): XataHttpDatabase<TSchema> & { $client: XataHttpClient };import { drizzle } from 'drizzle-orm/xata-http';
import { getXataClient } from './xata';
import * as schema from './schema';
const xata = getXataClient();
const db = drizzle(xata.sql, { schema });
// Query
const users = await db.select().from(schema.users);import { migrate } from 'drizzle-orm/xata-http/migrator';
await migrate(db, {
migrationsFolder: './drizzle',
});Uses postgres-js driver for Supabase PostgreSQL.
npm install drizzle-orm postgresimport { drizzle } from 'drizzle-orm/postgres-js';
import postgres from 'postgres';import { drizzle } from 'drizzle-orm/postgres-js';
import postgres from 'postgres';
import * as schema from './schema';
// Connection string from Supabase dashboard
const client = postgres(process.env.SUPABASE_DATABASE_URL);
const db = drizzle(client, { schema });
// Query
const users = await db.select().from(schema.users);Node.js MySQL driver using mysql2 package.
npm install drizzle-orm mysql2import { drizzle } from 'drizzle-orm/mysql2';
import mysql from 'mysql2/promise';function drizzle<TSchema extends Record<string, unknown> = Record<string, never>>(
client: Pool | Connection | string,
config?: MySql2DrizzleConfig<TSchema>
): MySql2Database<TSchema> & { $client: Pool | Connection };
type MySql2DrizzleConfig<TSchema> = Omit<DrizzleConfig<TSchema>, 'schema'> & (
| { schema: TSchema; mode: 'default' | 'planetscale' }
| { schema?: undefined; mode?: 'default' | 'planetscale' }
);interface MySql2DrizzleConfig<TSchema> extends DrizzleConfig<TSchema> {
// Query mode - required when using schema
mode?: 'default' | 'planetscale';
// 'default' - supports prepared statements, transactions
// 'planetscale' - HTTP-based, no prepared statements
}import { drizzle } from 'drizzle-orm/mysql2';
import mysql from 'mysql2/promise';
import * as schema from './schema';
// Using connection pool
const pool = mysql.createPool({
host: 'localhost',
user: 'root',
database: 'mydb',
password: 'password',
waitForConnections: true,
connectionLimit: 10,
});
const db = drizzle(pool, { schema, mode: 'default' });
// Using connection string
const db2 = drizzle('mysql://user:pass@host:3306/dbname', {
schema,
mode: 'default',
});
// Using config object
const db3 = drizzle({
connection: {
host: 'localhost',
user: 'root',
database: 'mydb',
password: 'password',
},
schema,
mode: 'default',
logger: true,
});
// Query
const users = await db.select().from(schema.users);import { migrate } from 'drizzle-orm/mysql2/migrator';
await migrate(db, {
migrationsFolder: './drizzle',
});Serverless MySQL driver for PlanetScale.
npm install drizzle-orm @planetscale/databaseimport { drizzle } from 'drizzle-orm/planetscale-serverless';
import { Client } from '@planetscale/database';function drizzle<TSchema extends Record<string, unknown> = Record<string, never>>(
client: Client | string,
config?: DrizzleConfig<TSchema>
): PlanetScaleDatabase<TSchema> & { $client: Client };
// Config-based
function drizzle<TSchema>(
config: DrizzleConfig<TSchema> & {
client?: Client;
connection?: string | Config;
}
): PlanetScaleDatabase<TSchema>;import { drizzle } from 'drizzle-orm/planetscale-serverless';
import { Client } from '@planetscale/database';
import * as schema from './schema';
// Using Client instance
const client = new Client({
host: process.env.DATABASE_HOST,
username: process.env.DATABASE_USERNAME,
password: process.env.DATABASE_PASSWORD,
});
const db = drizzle(client, { schema });
// Using connection string
const db2 = drizzle(process.env.DATABASE_URL, { schema });
// Using config
const db3 = drizzle({
connection: {
host: process.env.DATABASE_HOST,
username: process.env.DATABASE_USERNAME,
password: process.env.DATABASE_PASSWORD,
},
schema,
logger: true,
});
// Query
const users = await db.select().from(schema.users);import { migrate } from 'drizzle-orm/planetscale-serverless/migrator';
await migrate(db, {
migrationsFolder: './drizzle',
});Serverless MySQL driver for TiDB Cloud.
npm install drizzle-orm @tidbcloud/serverlessimport { drizzle } from 'drizzle-orm/tidb-serverless';
import { connect } from '@tidbcloud/serverless';function drizzle<TSchema extends Record<string, unknown> = Record<string, never>>(
client: Connection | string,
config?: DrizzleConfig<TSchema>
): TiDBServerlessDatabase<TSchema> & { $client: Connection };
// Config-based
function drizzle<TSchema>(
config: DrizzleConfig<TSchema> & {
client?: Connection;
connection?: string | Config;
}
): TiDBServerlessDatabase<TSchema>;import { drizzle } from 'drizzle-orm/tidb-serverless';
import { connect } from '@tidbcloud/serverless';
import * as schema from './schema';
// Using connection
const connection = connect({
url: process.env.DATABASE_URL,
});
const db = drizzle(connection, { schema });
// Using connection string
const db2 = drizzle(process.env.DATABASE_URL, { schema });
// Using config
const db3 = drizzle({
connection: {
url: process.env.DATABASE_URL,
},
schema,
logger: true,
});
// Query
const users = await db.select().from(schema.users);import { migrate } from 'drizzle-orm/tidb-serverless/migrator';
await migrate(db, {
migrationsFolder: './drizzle',
});Custom proxy driver for remote MySQL execution.
npm install drizzle-ormimport { drizzle } from 'drizzle-orm/mysql-proxy';type RemoteCallback = (
sql: string,
params: any[],
method: 'all' | 'execute',
typings?: any[]
) => Promise<{ rows: any[] }>;
function drizzle<TSchema extends Record<string, unknown> = Record<string, never>>(
callback: RemoteCallback,
config?: DrizzleConfig<TSchema>
): MySqlRemoteDatabase<TSchema>;import { drizzle } from 'drizzle-orm/mysql-proxy';
import * as schema from './schema';
const callback: RemoteCallback = async (sql, params, method) => {
const response = await fetch('https://api.example.com/sql', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ sql, params, method }),
});
const { rows } = await response.json();
return { rows };
};
const db = drizzle(callback, { schema, mode: 'default' });
// Query
const users = await db.select().from(schema.users);import { migrate } from 'drizzle-orm/mysql-proxy/migrator';
await migrate(db, {
migrationsFolder: './drizzle',
});Synchronous SQLite driver for Node.js.
npm install drizzle-orm better-sqlite3
npm install -D @types/better-sqlite3import { drizzle } from 'drizzle-orm/better-sqlite3';
import Database from 'better-sqlite3';function drizzle<TSchema extends Record<string, unknown> = Record<string, never>>(
client?: Database | string,
config?: DrizzleConfig<TSchema>
): BetterSQLite3Database<TSchema> & { $client: Database };
// Config-based
function drizzle<TSchema>(
config: DrizzleConfig<TSchema> & {
client?: Database;
connection?: string | Buffer | (Options & { source?: string | Buffer });
}
): BetterSQLite3Database<TSchema>;import { drizzle } from 'drizzle-orm/better-sqlite3';
import Database from 'better-sqlite3';
import * as schema from './schema';
// Using Database instance
const sqlite = new Database('sqlite.db');
const db = drizzle(sqlite, { schema });
// Using file path
const db2 = drizzle('sqlite.db', { schema });
// In-memory database
const db3 = drizzle(':memory:', { schema });
// With options
const db4 = drizzle({
connection: {
source: 'sqlite.db',
readonly: false,
fileMustExist: false,
timeout: 5000,
},
schema,
logger: true,
});
// Query (synchronous)
const users = db.select().from(schema.users).all();import { migrate } from 'drizzle-orm/better-sqlite3/migrator';
migrate(db, {
migrationsFolder: './drizzle',
});Native SQLite driver for Bun runtime.
bun add drizzle-ormimport { drizzle } from 'drizzle-orm/bun-sqlite';
import { Database } from 'bun:sqlite';function drizzle<TSchema extends Record<string, unknown> = Record<string, never>>(
client?: Database | string,
config?: DrizzleConfig<TSchema>
): BunSQLiteDatabase<TSchema> & { $client: Database };
// Config-based
function drizzle<TSchema>(
config: DrizzleConfig<TSchema> & {
client?: Database;
connection?: string | { source?: string; readonly?: boolean };
}
): BunSQLiteDatabase<TSchema>;import { drizzle } from 'drizzle-orm/bun-sqlite';
import { Database } from 'bun:sqlite';
import * as schema from './schema';
// Using Bun Database
const sqlite = new Database('sqlite.db');
const db = drizzle(sqlite, { schema });
// Using file path
const db2 = drizzle('sqlite.db', { schema });
// In-memory
const db3 = drizzle(':memory:', { schema });
// With options
const db4 = drizzle({
connection: {
source: 'sqlite.db',
readonly: false,
},
schema,
});
// Query (synchronous)
const users = db.select().from(schema.users).all();import { migrate } from 'drizzle-orm/bun-sqlite/migrator';
migrate(db, {
migrationsFolder: './drizzle',
});SQLite driver for libSQL (Turso) with local, remote, and replica modes.
npm install drizzle-orm @libsql/clientimport { drizzle } from 'drizzle-orm/libsql';
import { createClient } from '@libsql/client';function drizzle<TSchema extends Record<string, unknown> = Record<string, never>>(
client: Client | string,
config?: DrizzleConfig<TSchema>
): LibSQLDatabase<TSchema> & { $client: Client };
// Config-based
function drizzle<TSchema>(
config: DrizzleConfig<TSchema> & {
client?: Client;
connection?: string | Config;
}
): LibSQLDatabase<TSchema>;
interface Config {
url: string;
authToken?: string;
syncUrl?: string; // For local replica mode
syncInterval?: number; // Sync interval in ms
encryptionKey?: string;
}import { drizzle } from 'drizzle-orm/libsql';
import { createClient } from '@libsql/client';
import * as schema from './schema';
// Remote database (Turso)
const client = createClient({
url: process.env.TURSO_DATABASE_URL,
authToken: process.env.TURSO_AUTH_TOKEN,
});
const db = drizzle(client, { schema });
// Local file
const db2 = drizzle('file:local.db', { schema });
// In-memory
const db3 = drizzle(':memory:', { schema });
// Local replica (sync from remote)
const db4 = drizzle({
connection: {
url: 'file:local.db',
syncUrl: process.env.TURSO_DATABASE_URL,
authToken: process.env.TURSO_AUTH_TOKEN,
syncInterval: 60000, // Sync every 60 seconds
},
schema,
});
// Query
const users = await db.select().from(schema.users);
// Manual sync (replica mode)
await db4.$client.sync();import { migrate } from 'drizzle-orm/libsql/migrator';
await migrate(db, {
migrationsFolder: './drizzle',
});SQLite driver for Cloudflare D1 (Workers).
npm install drizzle-orm
npm install -D @cloudflare/workers-typesimport { drizzle } from 'drizzle-orm/d1';function drizzle<TSchema extends Record<string, unknown> = Record<string, never>>(
client: D1Database,
config?: DrizzleConfig<TSchema>
): DrizzleD1Database<TSchema> & { $client: D1Database };import { drizzle } from 'drizzle-orm/d1';
import * as schema from './schema';
// In Cloudflare Worker
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const db = drizzle(env.DB, { schema });
const users = await db.select().from(schema.users);
return Response.json(users);
},
};
// In Pages Functions
export async function onRequest(context) {
const db = drizzle(context.env.DB, { schema });
const users = await db.select().from(schema.users);
return Response.json(users);
}const [users, posts] = await db.batch([
db.select().from(schema.users),
db.select().from(schema.posts),
]);import { migrate } from 'drizzle-orm/d1/migrator';
// Run migrations in Worker
await migrate(db, {
migrationsFolder: './drizzle',
});SQLite driver for React Native Expo.
npm install drizzle-orm expo-sqliteimport { drizzle } from 'drizzle-orm/expo-sqlite';
import { openDatabaseSync } from 'expo-sqlite';function drizzle<TSchema extends Record<string, unknown> = Record<string, never>>(
client: SQLiteDatabase,
config?: DrizzleConfig<TSchema>
): ExpoSQLiteDatabase<TSchema> & { $client: SQLiteDatabase };import { drizzle } from 'drizzle-orm/expo-sqlite';
import { openDatabaseSync } from 'expo-sqlite';
import * as schema from './schema';
// Open database
const expo = openDatabaseSync('mydb.db');
const db = drizzle(expo, { schema });
// Query
const users = await db.select().from(schema.users);
// Insert
await db.insert(schema.users).values({
name: 'John',
email: 'john@example.com',
});import { migrate } from 'drizzle-orm/expo-sqlite/migrator';
import migrations from './drizzle/migrations';
// Run migrations on app startup
migrate(db, { migrations });High-performance SQLite driver for React Native.
npm install drizzle-orm @op-engineering/op-sqliteimport { drizzle } from 'drizzle-orm/op-sqlite';
import { open } from '@op-engineering/op-sqlite';function drizzle<TSchema extends Record<string, unknown> = Record<string, never>>(
client: OPSQLiteDatabase,
config?: DrizzleConfig<TSchema>
): OPSQLiteDatabase<TSchema> & { $client: OPSQLiteDatabase };import { drizzle } from 'drizzle-orm/op-sqlite';
import { open } from '@op-engineering/op-sqlite';
import * as schema from './schema';
// Open database
const opsqlite = open({ name: 'mydb.db' });
const db = drizzle(opsqlite, { schema });
// Query
const users = db.select().from(schema.users).all();import { migrate } from 'drizzle-orm/op-sqlite/migrator';
migrate(db, {
migrationsFolder: './drizzle',
});WASM SQLite for browsers.
npm install drizzle-orm sql.jsimport { drizzle } from 'drizzle-orm/sql-js';
import initSqlJs from 'sql.js';function drizzle<TSchema extends Record<string, unknown> = Record<string, never>>(
client: SqlJsDatabase,
config?: DrizzleConfig<TSchema>
): SqlJsDatabase<TSchema> & { $client: SqlJsDatabase };import { drizzle } from 'drizzle-orm/sql-js';
import initSqlJs from 'sql.js';
import * as schema from './schema';
// Initialize sql.js
const SQL = await initSqlJs({
locateFile: (file) => `https://sql.js.org/dist/${file}`,
});
// Create database
const sqlite = new SQL.Database();
const db = drizzle(sqlite, { schema });
// Query (synchronous)
const users = db.select().from(schema.users).all();
// Export database
const data = sqlite.export();
const buffer = Buffer.from(data);
// Save to file or localStorageimport { migrate } from 'drizzle-orm/sql-js/migrator';
migrate(db, {
migrationsFolder: './drizzle',
});Custom proxy driver for remote SQLite execution.
npm install drizzle-ormimport { drizzle } from 'drizzle-orm/sqlite-proxy';type RemoteCallback = (
sql: string,
params: any[],
method: 'run' | 'all' | 'values' | 'get'
) => Promise<{ rows: any[] }>;
function drizzle<TSchema extends Record<string, unknown> = Record<string, never>>(
callback: RemoteCallback,
config?: DrizzleConfig<TSchema>
): SQLiteRemoteDatabase<TSchema>;import { drizzle } from 'drizzle-orm/sqlite-proxy';
import * as schema from './schema';
const callback: RemoteCallback = async (sql, params, method) => {
const response = await fetch('https://api.example.com/sql', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ sql, params, method }),
});
const { rows } = await response.json();
return { rows };
};
const db = drizzle(callback, { schema });
// Query
const users = await db.select().from(schema.users);import { migrate } from 'drizzle-orm/sqlite-proxy/migrator';
await migrate(db, {
migrationsFolder: './drizzle',
});SQLite driver for Cloudflare Durable Objects.
npm install drizzle-orm
npm install -D @cloudflare/workers-typesimport { drizzle } from 'drizzle-orm/durable-sqlite';function drizzle<TSchema extends Record<string, unknown> = Record<string, never>>(
client: DurableObjectStorage,
config?: DrizzleConfig<TSchema>
): DurableSQLiteDatabase<TSchema> & { $client: DurableObjectStorage };import { drizzle } from 'drizzle-orm/durable-sqlite';
import * as schema from './schema';
// In Durable Object
export class MyDurableObject {
sql: DurableSQLiteDatabase<typeof schema>;
constructor(state: DurableObjectState, env: Env) {
this.sql = drizzle(state.storage, { schema });
}
async fetch(request: Request): Promise<Response> {
const users = await this.sql.select().from(schema.users);
return Response.json(users);
}
}import { migrate } from 'drizzle-orm/durable-sqlite/migrator';
await migrate(db, {
migrationsFolder: './drizzle',
});SingleStore (MemSQL) driver using mysql2.
npm install drizzle-orm mysql2import { drizzle } from 'drizzle-orm/singlestore';
import mysql from 'mysql2/promise';function drizzle<TSchema extends Record<string, unknown> = Record<string, never>>(
client: Pool | Connection | string,
config?: SingleStoreDriverConfig<TSchema>
): SingleStoreDatabase<TSchema> & { $client: Pool | Connection };import { drizzle } from 'drizzle-orm/singlestore';
import mysql from 'mysql2/promise';
import * as schema from './schema';
// Connection pool
const pool = mysql.createPool({
host: 'localhost',
user: 'root',
database: 'mydb',
password: 'password',
});
const db = drizzle(pool, { schema });
// Query
const users = await db.select().from(schema.users);import { migrate } from 'drizzle-orm/singlestore/migrator';
await migrate(db, {
migrationsFolder: './drizzle',
});Proxy driver for remote SingleStore execution.
npm install drizzle-ormimport { drizzle } from 'drizzle-orm/singlestore-proxy';type RemoteCallback = (
sql: string,
params: any[],
method: 'all' | 'execute'
) => Promise<{ rows: any[] }>;
function drizzle<TSchema extends Record<string, unknown> = Record<string, never>>(
callback: RemoteCallback,
config?: DrizzleConfig<TSchema>
): SingleStoreRemoteDatabase<TSchema>;import { drizzle } from 'drizzle-orm/singlestore-proxy';
import * as schema from './schema';
const callback: RemoteCallback = async (sql, params, method) => {
const response = await fetch('https://api.example.com/sql', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ sql, params, method }),
});
const { rows } = await response.json();
return { rows };
};
const db = drizzle(callback, { schema });
// Query
const users = await db.select().from(schema.users);EdgeDB-like database driver.
npm install drizzle-ormimport { drizzle } from 'drizzle-orm/gel';function drizzle<TSchema extends Record<string, unknown> = Record<string, never>>(
client: GelClient,
config?: DrizzleConfig<TSchema>
): GelDatabase<TSchema> & { $client: GelClient };import { drizzle } from 'drizzle-orm/gel';
import * as schema from './schema';
// Create database instance
const db = drizzle(gelClient, { schema });
// Query
const users = await db.select().from(schema.users);import { migrate } from 'drizzle-orm/gel/migrator';
await migrate(db, {
migrationsFolder: './drizzle',
});Use Drizzle ORM with Prisma Client.
npm install drizzle-orm @prisma/clientimport { drizzle } from 'drizzle-orm/prisma/pg';
import { PrismaClient } from '@prisma/client';
import * as schema from './schema';
const prisma = new PrismaClient();
const db = drizzle(prisma, { schema });
// Use Drizzle queries
const users = await db.select().from(schema.users);
// Use Prisma client
const user = await prisma.user.findUnique({
where: { id: 1 },
});import { drizzle } from 'drizzle-orm/prisma/mysql';
import { PrismaClient } from '@prisma/client';
import * as schema from './schema';
const prisma = new PrismaClient();
const db = drizzle(prisma, { schema });
const users = await db.select().from(schema.users);import { drizzle } from 'drizzle-orm/prisma/sqlite';
import { PrismaClient } from '@prisma/client';
import * as schema from './schema';
const prisma = new PrismaClient();
const db = drizzle(prisma, { schema });
const users = await db.select().from(schema.users);Use Drizzle ORM with Knex.js query builder.
npm install drizzle-orm kneximport { drizzle } from 'drizzle-orm/knex';
import knex from 'knex';
import * as schema from './schema';
const knexInstance = knex({
client: 'pg',
connection: process.env.DATABASE_URL,
});
const db = drizzle(knexInstance, { schema });
// Use Drizzle queries
const users = await db.select().from(schema.users);
// Use Knex queries
const user = await knexInstance('users').where('id', 1).first();Use Drizzle ORM with Kysely query builder.
npm install drizzle-orm kyselyimport { drizzle } from 'drizzle-orm/kysely';
import { Kysely, PostgresDialect } from 'kysely';
import { Pool } from 'pg';
import * as schema from './schema';
const kysely = new Kysely({
dialect: new PostgresDialect({
pool: new Pool({
connectionString: process.env.DATABASE_URL,
}),
}),
});
const db = drizzle(kysely, { schema });
// Use Drizzle queries
const users = await db.select().from(schema.users);
// Use Kysely queries
const user = await kysely
.selectFrom('users')
.where('id', '=', 1)
.selectAll()
.executeTakeFirst();Configuration object accepted by all drizzle() functions:
interface DrizzleConfig<TSchema extends Record<string, unknown> = Record<string, never>> {
/**
* Schema definitions for relational queries
* Required for db.query.* API
*/
schema?: TSchema;
/**
* Logger configuration
* - true: Use DefaultLogger (console.log)
* - false: Disable logging
* - Logger instance: Custom logger implementation
*/
logger?: Logger | boolean;
/**
* Automatic column name casing conversion
* - 'snake_case': Convert camelCase to snake_case
* - 'camelCase': Convert snake_case to camelCase
*/
casing?: 'snake_case' | 'camelCase';
/**
* Cache instance for query result caching
*/
cache?: Cache;
}interface Logger {
logQuery(query: string, params: unknown[]): void;
}
// Built-in loggers
class DefaultLogger implements Logger {
logQuery(query: string, params: unknown[]): void {
console.log('Query:', query);
console.log('Params:', params);
}
}
class NoopLogger implements Logger {
logQuery(): void {}
}interface Cache {
get(key: string): Promise<any | undefined>;
set(key: string, value: any, ttl?: number): Promise<void>;
delete(key: string): Promise<void>;
clear(): Promise<void>;
onMutate?(tables: string[]): Promise<void>;
}Configure read replicas for load balancing across PostgreSQL, MySQL, and SQLite.
import { drizzle } from 'drizzle-orm/node-postgres';
import { withReplicas } from 'drizzle-orm/pg-core';
import { Pool } from 'pg';
import * as schema from './schema';
const primary = drizzle(new Pool({
connectionString: process.env.PRIMARY_DATABASE_URL,
}), { schema });
const read1 = drizzle(new Pool({
connectionString: process.env.READ_REPLICA_1_URL,
}), { schema });
const read2 = drizzle(new Pool({
connectionString: process.env.READ_REPLICA_2_URL,
}), { schema });
const db = withReplicas(primary, [read1, read2]);
// Writes go to primary
await db.insert(schema.users).values({ name: 'John' });
// Reads use replicas (round-robin)
const users = await db.select().from(schema.users);
// Force read from primary
const user = await db.$primary.select().from(schema.users).where(eq(schema.users.id, 1));import { drizzle } from 'drizzle-orm/mysql2';
import { withReplicas } from 'drizzle-orm/mysql-core';
import mysql from 'mysql2/promise';
import * as schema from './schema';
const primary = drizzle(mysql.createPool({
host: 'primary.example.com',
user: 'root',
database: 'mydb',
}), { schema, mode: 'default' });
const read1 = drizzle(mysql.createPool({
host: 'read1.example.com',
user: 'root',
database: 'mydb',
}), { schema, mode: 'default' });
const db = withReplicas(primary, [read1]);
// Writes to primary, reads from replicas
await db.insert(schema.users).values({ name: 'John' });
const users = await db.select().from(schema.users);import { drizzle } from 'drizzle-orm/libsql';
import { withReplicas } from 'drizzle-orm/sqlite-core';
import { createClient } from '@libsql/client';
import * as schema from './schema';
const primary = drizzle(createClient({
url: 'file:primary.db',
}), { schema });
const replica = drizzle(createClient({
url: 'file:replica.db',
}), { schema });
const db = withReplicas(primary, [replica]);
// Writes to primary, reads from replicas
await db.insert(schema.users).values({ name: 'John' });
const users = await db.select().from(schema.users);db.$primary to force primary readsThese drivers have built-in migrate() function:
postgres-js - import { migrate } from 'drizzle-orm/postgres-js/migrator'node-postgres - import { migrate } from 'drizzle-orm/node-postgres/migrator'neon-serverless - import { migrate } from 'drizzle-orm/neon-serverless/migrator'neon-http - import { migrate } from 'drizzle-orm/neon-http/migrator'vercel-postgres - import { migrate } from 'drizzle-orm/vercel-postgres/migrator'aws-data-api/pg - import { migrate } from 'drizzle-orm/aws-data-api/pg/migrator'pglite - import { migrate } from 'drizzle-orm/pglite/migrator'pg-proxy - import { migrate } from 'drizzle-orm/pg-proxy/migrator'xata-http - import { migrate } from 'drizzle-orm/xata-http/migrator'mysql2 - import { migrate } from 'drizzle-orm/mysql2/migrator'planetscale-serverless - import { migrate } from 'drizzle-orm/planetscale-serverless/migrator'tidb-serverless - import { migrate } from 'drizzle-orm/tidb-serverless/migrator'mysql-proxy - import { migrate } from 'drizzle-orm/mysql-proxy/migrator'better-sqlite3 - import { migrate } from 'drizzle-orm/better-sqlite3/migrator'bun-sqlite - import { migrate } from 'drizzle-orm/bun-sqlite/migrator'libsql - import { migrate } from 'drizzle-orm/libsql/migrator'd1 - import { migrate } from 'drizzle-orm/d1/migrator'expo-sqlite - import { migrate } from 'drizzle-orm/expo-sqlite/migrator'op-sqlite - import { migrate } from 'drizzle-orm/op-sqlite/migrator'sql-js - import { migrate } from 'drizzle-orm/sql-js/migrator'sqlite-proxy - import { migrate } from 'drizzle-orm/sqlite-proxy/migrator'durable-sqlite - import { migrate } from 'drizzle-orm/durable-sqlite/migrator'singlestore - import { migrate } from 'drizzle-orm/singlestore/migrator'singlestore-proxy - import { migrate } from 'drizzle-orm/singlestore-proxy/migrator'gel - import { migrate } from 'drizzle-orm/gel/migrator'interface MigrationConfig {
// Directory containing migration files
migrationsFolder: string;
// Table name for migration tracking (default: '__drizzle_migrations')
migrationsTable?: string;
// Schema name for migration table (PostgreSQL only, default: 'drizzle')
migrationsSchema?: string;
}import { drizzle } from 'drizzle-orm/postgres-js';
import { migrate } from 'drizzle-orm/postgres-js/migrator';
import postgres from 'postgres';
const sql = postgres(process.env.DATABASE_URL, { max: 1 });
const db = drizzle(sql);
// Run migrations
await migrate(db, {
migrationsFolder: './drizzle',
migrationsTable: 'migrations',
migrationsSchema: 'public',
});
await sql.end();import { drizzle } from 'drizzle-orm/node-postgres';
import { Pool } from 'pg';
const pool = new Pool({
connectionString: process.env.DATABASE_URL,
max: 20, // Max connections
idleTimeoutMillis: 30000, // Close idle connections after 30s
connectionTimeoutMillis: 2000, // Timeout for new connections
});
const db = drizzle(pool);import { drizzle } from 'drizzle-orm/mysql2';
import mysql from 'mysql2/promise';
const pool = mysql.createPool({
host: 'localhost',
user: 'root',
database: 'mydb',
waitForConnections: true,
connectionLimit: 10,
maxIdle: 10,
idleTimeout: 60000,
queueLimit: 0,
enableKeepAlive: true,
keepAliveInitialDelay: 0,
});
const db = drizzle(pool, { mode: 'default' });| Driver | Platform | Async | Transactions | Prepared Statements | Batch Queries | Migrations | Read Replicas |
|---|---|---|---|---|---|---|---|
| PostgreSQL | |||||||
| node-postgres | Node.js | Yes | Yes | Yes | No | Yes | Yes |
| postgres-js | Node.js | Yes | Yes | Yes | No | Yes | Yes |
| neon-serverless | Serverless | Yes | Yes | Yes | No | Yes | Yes |
| neon-http | Edge | Yes | Yes | No | Yes | Yes | No |
| vercel-postgres | Vercel | Yes | Yes | Yes | No | Yes | Yes |
| aws-data-api | Serverless | Yes | Yes | No | No | Yes | No |
| pglite | Node.js/Browser | Yes | Yes | Yes | No | Yes | Yes |
| pg-proxy | Custom | Yes | Yes | No | No | Yes | Yes |
| xata-http | Edge | Yes | Yes | No | No | Yes | No |
| MySQL | |||||||
| mysql2 | Node.js | Yes | Yes | Yes | No | Yes | Yes |
| planetscale | Serverless | Yes | Yes | No | No | Yes | No |
| tidb-serverless | Serverless | Yes | Yes | No | No | Yes | No |
| mysql-proxy | Custom | Yes | Yes | No | No | Yes | Yes |
| SQLite | |||||||
| better-sqlite3 | Node.js | No | Yes | Yes | No | Yes | Yes |
| bun-sqlite | Bun | No | Yes | Yes | No | Yes | Yes |
| libsql | Multi-platform | Yes | Yes | Yes | Yes | Yes | Yes |
| d1 | Cloudflare | Yes | Yes | No | Yes | Yes | No |
| expo-sqlite | React Native | Yes | Yes | No | No | Yes | No |
| op-sqlite | React Native | No | Yes | Yes | No | Yes | No |
| sql.js | Browser | No | Yes | No | No | Yes | No |
| sqlite-proxy | Custom | Yes | Yes | No | No | Yes | Yes |
| durable-sqlite | Cloudflare | Yes | Yes | No | No | Yes | No |
| SingleStore | |||||||
| singlestore | Node.js | Yes | Yes | Yes | No | Yes | Yes |
| singlestore-proxy | Custom | Yes | Yes | No | No | Yes | Yes |
| GEL | |||||||
| gel | Node.js | Yes | Yes | Yes | No | Yes | Yes |
// Good: Reuse connection pool
const pool = new Pool({ /* config */ });
const db = drizzle(pool);
// Bad: Create new connection per request
app.get('/users', async (req, res) => {
const pool = new Pool({ /* config */ }); // Don't do this!
const db = drizzle(pool);
// ...
});
// Good: Close connections on shutdown
process.on('SIGTERM', async () => {
await pool.end();
process.exit(0);
});// Development
const db = drizzle(pool, {
schema,
logger: true, // Log all queries
casing: 'camelCase',
});
// Production
const db = drizzle(pool, {
schema,
logger: false, // Disable logging
casing: 'camelCase',
cache: new UpstashCache(redis), // Enable caching
});import { drizzle } from 'drizzle-orm/postgres-js';
import postgres from 'postgres';
try {
const sql = postgres(process.env.DATABASE_URL);
const db = drizzle(sql);
const users = await db.select().from(schema.users);
} catch (error) {
if (error.code === 'ECONNREFUSED') {
console.error('Database connection refused');
} else if (error.code === '42P01') {
console.error('Table does not exist');
} else {
console.error('Database error:', error);
}
}Install with Tessl CLI
npx tessl i tessl/npm-drizzle-orm