or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

examples

edge-cases.mdreal-world-scenarios.md
index.md
tile.json

drivers.mddocs/reference/

Database Drivers

Complete reference for all Drizzle ORM database drivers, including PostgreSQL, MySQL, SQLite, SingleStore, and GEL drivers, plus integration adapters.

Overview

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.

Driver Categories

  • PostgreSQL: 10 drivers (pg, postgres-js, Neon serverless/HTTP, Vercel Postgres, AWS RDS Data API, PGlite, pg-proxy, Xata HTTP, Supabase)
  • MySQL: 4 drivers (mysql2, PlanetScale, TiDB, mysql-proxy)
  • SQLite: 9 drivers (better-sqlite3, Bun SQLite, libSQL/Turso, Cloudflare D1, Expo SQLite, OP SQLite, sql.js, sqlite-proxy, Durable SQLite)
  • SingleStore: 2 drivers (singlestore, singlestore-proxy)
  • GEL: 1 driver (EdgeDB-like)
  • Integrations: Prisma, Knex, Kysely adapters

PostgreSQL Drivers

node-postgres (pg)

Node.js PostgreSQL driver using the official pg package.

Installation { .api }

npm install drizzle-orm pg
npm install -D @types/pg

Import { .api }

import { drizzle } from 'drizzle-orm/node-postgres';
import { Pool } from 'pg';

Function Signature { .api }

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

Configuration Options { .api }

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
}

Basic Usage { .api }

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

Migration Support { .api }

import { migrate } from 'drizzle-orm/node-postgres/migrator';

await migrate(db, {
  migrationsFolder: './drizzle',
  migrationsTable: 'migrations',
  migrationsSchema: 'public',
});

Features

  • Connection pooling via Pool
  • Prepared statements
  • Transactions with isolation levels
  • Read replicas support via withReplicas()
  • Full PostgreSQL feature support

postgres-js

High-performance PostgreSQL driver using postgres (postgres.js).

Installation { .api }

npm install drizzle-orm postgres

Import { .api }

import { drizzle } from 'drizzle-orm/postgres-js';
import postgres from 'postgres';

Function Signature { .api }

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

Basic Usage { .api }

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

Migration Support { .api }

import { migrate } from 'drizzle-orm/postgres-js/migrator';

await migrate(db, {
  migrationsFolder: './drizzle',
});

Features

  • High performance with connection pooling
  • Automatic date/timestamp parsing disabled (raw strings returned)
  • Prepared statements
  • Transactions
  • Read replicas support
  • Full PostgreSQL feature support

Neon Serverless

Serverless PostgreSQL driver for Neon with WebSocket support.

Installation { .api }

npm install drizzle-orm @neondatabase/serverless

Import { .api }

import { drizzle } from 'drizzle-orm/neon-serverless';
import { Pool } from '@neondatabase/serverless';

Function Signature { .api }

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

Basic Usage { .api }

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

Migration Support { .api }

import { migrate } from 'drizzle-orm/neon-serverless/migrator';

await migrate(db, {
  migrationsFolder: './drizzle',
});

Features

  • Serverless-optimized (low latency)
  • WebSocket connections for edge runtimes
  • Connection pooling
  • Transactions
  • Full PostgreSQL feature support

Neon HTTP

HTTP-based serverless driver for Neon (no WebSocket required).

Installation { .api }

npm install drizzle-orm @neondatabase/serverless

Import { .api }

import { drizzle } from 'drizzle-orm/neon-http';
import { neon } from '@neondatabase/serverless';

Function Signature { .api }

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

Basic Usage { .api }

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

Batch Queries { .api }

const [users, posts] = await db.batch([
  db.select().from(schema.users),
  db.select().from(schema.posts),
]);

Migration Support { .api }

import { migrate } from 'drizzle-orm/neon-http/migrator';

await migrate(db, {
  migrationsFolder: './drizzle',
});

Features

  • Pure HTTP (works in all edge runtimes)
  • No WebSocket required
  • Batch query support
  • Auth token support for RLS
  • Ideal for Cloudflare Workers, Deno Deploy
  • Automatic type parsing disabled

Vercel Postgres

Vercel's PostgreSQL driver built on postgres.js.

Installation { .api }

npm install drizzle-orm @vercel/postgres

Import { .api }

import { drizzle } from 'drizzle-orm/vercel-postgres';
import { sql } from '@vercel/postgres';

Function Signature { .api }

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

Basic Usage { .api }

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

Migration Support { .api }

import { migrate } from 'drizzle-orm/vercel-postgres/migrator';

await migrate(db, {
  migrationsFolder: './drizzle',
});

Features

  • Automatic environment variable detection
  • Optimized for Vercel Edge Runtime
  • Connection pooling
  • Re-exports from postgres-js driver

AWS RDS Data API

Serverless PostgreSQL/MySQL driver using AWS RDS Data API.

Installation { .api }

npm install drizzle-orm @aws-sdk/client-rds-data

Import (PostgreSQL) { .api }

import { drizzle } from 'drizzle-orm/aws-data-api/pg';
import { RDSDataClient } from '@aws-sdk/client-rds-data';

Function Signature { .api }

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
}

Basic Usage { .api }

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

Migration Support { .api }

import { migrate } from 'drizzle-orm/aws-data-api/pg/migrator';

await migrate(db, {
  migrationsFolder: './drizzle',
});

Features

  • Serverless (no connection management)
  • Works with Aurora Serverless v1/v2
  • Automatic transaction management
  • Array type casting for PostgreSQL
  • Supports both PostgreSQL and MySQL modes

PGlite

Embedded WASM PostgreSQL for Node.js and browsers.

Installation { .api }

npm install drizzle-orm @electric-sql/pglite

Import { .api }

import { drizzle } from 'drizzle-orm/pglite';
import { PGlite } from '@electric-sql/pglite';

Function Signature { .api }

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

Basic Usage { .api }

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

Migration Support { .api }

import { migrate } from 'drizzle-orm/pglite/migrator';

await migrate(db, {
  migrationsFolder: './drizzle',
});

Features

  • Embedded PostgreSQL (no server required)
  • Works in Node.js and browsers
  • In-memory or persistent storage
  • Full PostgreSQL compatibility
  • Synchronous and asynchronous APIs

pg-proxy

Custom proxy driver for remote PostgreSQL execution.

Installation { .api }

npm install drizzle-orm

Import { .api }

import { drizzle } from 'drizzle-orm/pg-proxy';

Function Signature { .api }

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

Basic Usage { .api }

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

Migration Support { .api }

import { migrate } from 'drizzle-orm/pg-proxy/migrator';

await migrate(db, {
  migrationsFolder: './drizzle',
});

Features

  • Custom remote execution
  • Useful for HTTP-based database access
  • Can implement custom auth/routing
  • Full PostgreSQL query support

Xata HTTP

HTTP driver for Xata's PostgreSQL service.

Installation { .api }

npm install drizzle-orm @xata.io/client

Import { .api }

import { drizzle } from 'drizzle-orm/xata-http';
import { getXataClient } from './xata'; // Generated Xata client

Function Signature { .api }

function drizzle<TSchema extends Record<string, unknown> = Record<string, never>>(
  client: XataHttpClient,
  config?: DrizzleConfig<TSchema>
): XataHttpDatabase<TSchema> & { $client: XataHttpClient };

Basic Usage { .api }

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

Migration Support { .api }

import { migrate } from 'drizzle-orm/xata-http/migrator';

await migrate(db, {
  migrationsFolder: './drizzle',
});

Features

  • HTTP-based (edge runtime compatible)
  • Integrated with Xata platform
  • Full PostgreSQL support
  • File attachments and search capabilities

Supabase

Uses postgres-js driver for Supabase PostgreSQL.

Installation { .api }

npm install drizzle-orm postgres

Import { .api }

import { drizzle } from 'drizzle-orm/postgres-js';
import postgres from 'postgres';

Basic Usage { .api }

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

Features

  • Full postgres-js features
  • Works with Supabase connection pooler
  • Row-level security support
  • Real-time subscriptions (via Supabase client)

MySQL Drivers

mysql2

Node.js MySQL driver using mysql2 package.

Installation { .api }

npm install drizzle-orm mysql2

Import { .api }

import { drizzle } from 'drizzle-orm/mysql2';
import mysql from 'mysql2/promise';

Function Signature { .api }

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

Configuration Options { .api }

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
}

Basic Usage { .api }

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

Migration Support { .api }

import { migrate } from 'drizzle-orm/mysql2/migrator';

await migrate(db, {
  migrationsFolder: './drizzle',
});

Features

  • Connection pooling
  • Prepared statements (default mode)
  • Transactions
  • Read replicas support
  • Full MySQL feature support

PlanetScale Serverless

Serverless MySQL driver for PlanetScale.

Installation { .api }

npm install drizzle-orm @planetscale/database

Import { .api }

import { drizzle } from 'drizzle-orm/planetscale-serverless';
import { Client } from '@planetscale/database';

Function Signature { .api }

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

Basic Usage { .api }

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

Migration Support { .api }

import { migrate } from 'drizzle-orm/planetscale-serverless/migrator';

await migrate(db, {
  migrationsFolder: './drizzle',
});

Features

  • HTTP-based (no TCP connections)
  • Edge runtime compatible
  • Automatic connection management
  • No prepared statements (uses 'planetscale' mode)
  • Optimized for serverless

TiDB Serverless

Serverless MySQL driver for TiDB Cloud.

Installation { .api }

npm install drizzle-orm @tidbcloud/serverless

Import { .api }

import { drizzle } from 'drizzle-orm/tidb-serverless';
import { connect } from '@tidbcloud/serverless';

Function Signature { .api }

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

Basic Usage { .api }

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

Migration Support { .api }

import { migrate } from 'drizzle-orm/tidb-serverless/migrator';

await migrate(db, {
  migrationsFolder: './drizzle',
});

Features

  • Serverless MySQL-compatible
  • HTTP-based connections
  • Edge runtime compatible
  • Compatible with TiDB Cloud
  • Horizontal scaling support

mysql-proxy

Custom proxy driver for remote MySQL execution.

Installation { .api }

npm install drizzle-orm

Import { .api }

import { drizzle } from 'drizzle-orm/mysql-proxy';

Function Signature { .api }

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

Basic Usage { .api }

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

Migration Support { .api }

import { migrate } from 'drizzle-orm/mysql-proxy/migrator';

await migrate(db, {
  migrationsFolder: './drizzle',
});

Features

  • Custom remote execution
  • HTTP-based database access
  • Custom auth/routing support
  • Full MySQL query support

SQLite Drivers

better-sqlite3

Synchronous SQLite driver for Node.js.

Installation { .api }

npm install drizzle-orm better-sqlite3
npm install -D @types/better-sqlite3

Import { .api }

import { drizzle } from 'drizzle-orm/better-sqlite3';
import Database from 'better-sqlite3';

Function Signature { .api }

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

Basic Usage { .api }

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

Migration Support { .api }

import { migrate } from 'drizzle-orm/better-sqlite3/migrator';

migrate(db, {
  migrationsFolder: './drizzle',
});

Features

  • Synchronous API (blocking)
  • High performance
  • WASM-free (native bindings)
  • Transactions
  • Prepared statements
  • Best for server-side Node.js

Bun SQLite

Native SQLite driver for Bun runtime.

Installation { .api }

bun add drizzle-orm

Import { .api }

import { drizzle } from 'drizzle-orm/bun-sqlite';
import { Database } from 'bun:sqlite';

Function Signature { .api }

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

Basic Usage { .api }

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

Migration Support { .api }

import { migrate } from 'drizzle-orm/bun-sqlite/migrator';

migrate(db, {
  migrationsFolder: './drizzle',
});

Features

  • Native Bun integration
  • Extremely fast (native C bindings)
  • Synchronous API
  • Transactions
  • Prepared statements
  • Optimized for Bun runtime

libSQL / Turso

SQLite driver for libSQL (Turso) with local, remote, and replica modes.

Installation { .api }

npm install drizzle-orm @libsql/client

Import { .api }

import { drizzle } from 'drizzle-orm/libsql';
import { createClient } from '@libsql/client';

Function Signature { .api }

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

Basic Usage { .api }

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

Migration Support { .api }

import { migrate } from 'drizzle-orm/libsql/migrator';

await migrate(db, {
  migrationsFolder: './drizzle',
});

Features

  • Local, remote, and replica modes
  • Edge function compatible
  • Embedded WASM mode
  • Transactions
  • Batch queries
  • Automatic sync for replicas

Cloudflare D1

SQLite driver for Cloudflare D1 (Workers).

Installation { .api }

npm install drizzle-orm
npm install -D @cloudflare/workers-types

Import { .api }

import { drizzle } from 'drizzle-orm/d1';

Function Signature { .api }

function drizzle<TSchema extends Record<string, unknown> = Record<string, never>>(
  client: D1Database,
  config?: DrizzleConfig<TSchema>
): DrizzleD1Database<TSchema> & { $client: D1Database };

Basic Usage { .api }

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

Batch Queries { .api }

const [users, posts] = await db.batch([
  db.select().from(schema.users),
  db.select().from(schema.posts),
]);

Migration Support { .api }

import { migrate } from 'drizzle-orm/d1/migrator';

// Run migrations in Worker
await migrate(db, {
  migrationsFolder: './drizzle',
});

Features

  • Cloudflare Workers/Pages integration
  • Edge runtime optimized
  • Batch query support
  • Transactions
  • Free tier available
  • Global distribution

Expo SQLite

SQLite driver for React Native Expo.

Installation { .api }

npm install drizzle-orm expo-sqlite

Import { .api }

import { drizzle } from 'drizzle-orm/expo-sqlite';
import { openDatabaseSync } from 'expo-sqlite';

Function Signature { .api }

function drizzle<TSchema extends Record<string, unknown> = Record<string, never>>(
  client: SQLiteDatabase,
  config?: DrizzleConfig<TSchema>
): ExpoSQLiteDatabase<TSchema> & { $client: SQLiteDatabase };

Basic Usage { .api }

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

Migration Support { .api }

import { migrate } from 'drizzle-orm/expo-sqlite/migrator';
import migrations from './drizzle/migrations';

// Run migrations on app startup
migrate(db, { migrations });

Features

  • React Native Expo integration
  • Asynchronous API
  • Transactions
  • Persistent storage on mobile
  • Cross-platform (iOS/Android)

OP SQLite

High-performance SQLite driver for React Native.

Installation { .api }

npm install drizzle-orm @op-engineering/op-sqlite

Import { .api }

import { drizzle } from 'drizzle-orm/op-sqlite';
import { open } from '@op-engineering/op-sqlite';

Function Signature { .api }

function drizzle<TSchema extends Record<string, unknown> = Record<string, never>>(
  client: OPSQLiteDatabase,
  config?: DrizzleConfig<TSchema>
): OPSQLiteDatabase<TSchema> & { $client: OPSQLiteDatabase };

Basic Usage { .api }

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

Migration Support { .api }

import { migrate } from 'drizzle-orm/op-sqlite/migrator';

migrate(db, {
  migrationsFolder: './drizzle',
});

Features

  • React Native optimized
  • Synchronous API (faster)
  • High performance
  • JSI-based (direct C++ binding)
  • Transactions

sql.js

WASM SQLite for browsers.

Installation { .api }

npm install drizzle-orm sql.js

Import { .api }

import { drizzle } from 'drizzle-orm/sql-js';
import initSqlJs from 'sql.js';

Function Signature { .api }

function drizzle<TSchema extends Record<string, unknown> = Record<string, never>>(
  client: SqlJsDatabase,
  config?: DrizzleConfig<TSchema>
): SqlJsDatabase<TSchema> & { $client: SqlJsDatabase };

Basic Usage { .api }

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 localStorage

Migration Support { .api }

import { migrate } from 'drizzle-orm/sql-js/migrator';

migrate(db, {
  migrationsFolder: './drizzle',
});

Features

  • Browser-based SQLite
  • WASM-powered
  • In-memory by default
  • Export/import database
  • Synchronous API
  • No backend required

sqlite-proxy

Custom proxy driver for remote SQLite execution.

Installation { .api }

npm install drizzle-orm

Import { .api }

import { drizzle } from 'drizzle-orm/sqlite-proxy';

Function Signature { .api }

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

Basic Usage { .api }

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

Migration Support { .api }

import { migrate } from 'drizzle-orm/sqlite-proxy/migrator';

await migrate(db, {
  migrationsFolder: './drizzle',
});

Features

  • Custom remote execution
  • HTTP-based database access
  • Custom auth/routing support
  • Full SQLite query support

Durable SQLite

SQLite driver for Cloudflare Durable Objects.

Installation { .api }

npm install drizzle-orm
npm install -D @cloudflare/workers-types

Import { .api }

import { drizzle } from 'drizzle-orm/durable-sqlite';

Function Signature { .api }

function drizzle<TSchema extends Record<string, unknown> = Record<string, never>>(
  client: DurableObjectStorage,
  config?: DrizzleConfig<TSchema>
): DurableSQLiteDatabase<TSchema> & { $client: DurableObjectStorage };

Basic Usage { .api }

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

Migration Support { .api }

import { migrate } from 'drizzle-orm/durable-sqlite/migrator';

await migrate(db, {
  migrationsFolder: './drizzle',
});

Features

  • Durable Objects integration
  • Persistent storage
  • Strongly consistent
  • Transactional storage API
  • Per-object SQLite database

SingleStore Drivers

singlestore

SingleStore (MemSQL) driver using mysql2.

Installation { .api }

npm install drizzle-orm mysql2

Import { .api }

import { drizzle } from 'drizzle-orm/singlestore';
import mysql from 'mysql2/promise';

Function Signature { .api }

function drizzle<TSchema extends Record<string, unknown> = Record<string, never>>(
  client: Pool | Connection | string,
  config?: SingleStoreDriverConfig<TSchema>
): SingleStoreDatabase<TSchema> & { $client: Pool | Connection };

Basic Usage { .api }

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

Migration Support { .api }

import { migrate } from 'drizzle-orm/singlestore/migrator';

await migrate(db, {
  migrationsFolder: './drizzle',
});

Features

  • MySQL-compatible API
  • High-performance analytics
  • Real-time data processing
  • Distributed SQL
  • Columnstore and rowstore tables

singlestore-proxy

Proxy driver for remote SingleStore execution.

Installation { .api }

npm install drizzle-orm

Import { .api }

import { drizzle } from 'drizzle-orm/singlestore-proxy';

Function Signature { .api }

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

Basic Usage { .api }

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

Features

  • Custom remote execution
  • HTTP-based access
  • Full SingleStore support

GEL Driver

EdgeDB-like database driver.

Installation { .api }

npm install drizzle-orm

Import { .api }

import { drizzle } from 'drizzle-orm/gel';

Function Signature { .api }

function drizzle<TSchema extends Record<string, unknown> = Record<string, never>>(
  client: GelClient,
  config?: DrizzleConfig<TSchema>
): GelDatabase<TSchema> & { $client: GelClient };

Basic Usage { .api }

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

Migration Support { .api }

import { migrate } from 'drizzle-orm/gel/migrator';

await migrate(db, {
  migrationsFolder: './drizzle',
});

Features

  • EdgeDB-like type system
  • Rich column types (duration, date types)
  • Access control policies
  • Schema-based organization

Integration Drivers

Prisma Adapters

Use Drizzle ORM with Prisma Client.

Installation { .api }

npm install drizzle-orm @prisma/client

PostgreSQL Adapter { .api }

import { 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 },
});

MySQL Adapter { .api }

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

SQLite Adapter { .api }

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

Features

  • Use both Prisma and Drizzle in same project
  • Access Prisma migrations
  • Use Prisma Studio
  • Gradual migration path

Knex Integration

Use Drizzle ORM with Knex.js query builder.

Installation { .api }

npm install drizzle-orm knex

Basic Usage { .api }

import { 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();

Features

  • Use both Knex and Drizzle
  • Access Knex migrations
  • Reuse existing Knex configuration

Kysely Integration

Use Drizzle ORM with Kysely query builder.

Installation { .api }

npm install drizzle-orm kysely

Basic Usage { .api }

import { 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();

Features

  • Use both Kysely and Drizzle
  • Type-safe queries with both builders
  • Reuse Kysely connection

Common Configuration

DrizzleConfig Interface { .api }

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

Logger Interface { .api }

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 {}
}

Cache Interface { .api }

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

Read Replicas

Configure read replicas for load balancing across PostgreSQL, MySQL, and SQLite.

PostgreSQL Read Replicas { .api }

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

MySQL Read Replicas { .api }

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

SQLite Read Replicas { .api }

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

Read Replica Features

  • Load balancing: Distribute read queries across replicas
  • Failover: Automatic fallback to primary if replicas unavailable
  • Round-robin: Default strategy for replica selection
  • Force primary: Use db.$primary to force primary reads
  • Write safety: All write operations always use primary

Migration Support by Driver

Drivers with Migrate Function

These drivers have built-in migrate() function:

PostgreSQL

  • 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'

MySQL

  • 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'

SQLite

  • 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

  • singlestore - import { migrate } from 'drizzle-orm/singlestore/migrator'
  • singlestore-proxy - import { migrate } from 'drizzle-orm/singlestore-proxy/migrator'

GEL

  • gel - import { migrate } from 'drizzle-orm/gel/migrator'

Migration Config { .api }

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

Migration Usage Example { .api }

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

Connection Pooling

PostgreSQL Pooling

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

MySQL Pooling

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 Feature Matrix

DriverPlatformAsyncTransactionsPrepared StatementsBatch QueriesMigrationsRead Replicas
PostgreSQL
node-postgresNode.jsYesYesYesNoYesYes
postgres-jsNode.jsYesYesYesNoYesYes
neon-serverlessServerlessYesYesYesNoYesYes
neon-httpEdgeYesYesNoYesYesNo
vercel-postgresVercelYesYesYesNoYesYes
aws-data-apiServerlessYesYesNoNoYesNo
pgliteNode.js/BrowserYesYesYesNoYesYes
pg-proxyCustomYesYesNoNoYesYes
xata-httpEdgeYesYesNoNoYesNo
MySQL
mysql2Node.jsYesYesYesNoYesYes
planetscaleServerlessYesYesNoNoYesNo
tidb-serverlessServerlessYesYesNoNoYesNo
mysql-proxyCustomYesYesNoNoYesYes
SQLite
better-sqlite3Node.jsNoYesYesNoYesYes
bun-sqliteBunNoYesYesNoYesYes
libsqlMulti-platformYesYesYesYesYesYes
d1CloudflareYesYesNoYesYesNo
expo-sqliteReact NativeYesYesNoNoYesNo
op-sqliteReact NativeNoYesYesNoYesNo
sql.jsBrowserNoYesNoNoYesNo
sqlite-proxyCustomYesYesNoNoYesYes
durable-sqliteCloudflareYesYesNoNoYesNo
SingleStore
singlestoreNode.jsYesYesYesNoYesYes
singlestore-proxyCustomYesYesNoNoYesYes
GEL
gelNode.jsYesYesYesNoYesYes

Best Practices

Driver Selection

  1. Node.js backend: Use native drivers (pg, mysql2, better-sqlite3)
  2. Edge runtimes: Use HTTP-based drivers (neon-http, planetscale, d1)
  3. Serverless functions: Use connection pooling or HTTP drivers
  4. React Native: Use expo-sqlite or op-sqlite
  5. Browsers: Use pglite, sql.js, or HTTP APIs
  6. High performance: Use postgres-js, better-sqlite3, or op-sqlite

Connection Management

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

Environment-Specific Configuration

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

Error Handling

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

See Also

  • Query Building - Query API reference
  • Schema Definition - Table and column definitions
  • PostgreSQL - PostgreSQL-specific features
  • MySQL - MySQL-specific features
  • SQLite - SQLite-specific features