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);
}
}