Modern, headless TypeScript ORM providing a thin typed layer on top of SQL with multi-database support and type safety
npx @tessl/cli install tessl/npm-drizzle-orm@0.44.0Drizzle ORM is a modern, headless TypeScript ORM for Node.js, TypeScript, and JavaScript that provides a thin typed layer on top of SQL. It supports PostgreSQL, MySQL, and SQLite databases with comprehensive type safety, zero dependencies, and excellent performance across multiple runtime environments.
npm install drizzle-ormimport { drizzle } from "drizzle-orm/node-postgres";
import { pgTable, serial, text, varchar } from "drizzle-orm/pg-core";
import { eq, and, or } from "drizzle-orm";For different database providers:
// PostgreSQL
import { drizzle } from "drizzle-orm/node-postgres";
import { drizzle } from "drizzle-orm/postgres-js";
import { drizzle } from "drizzle-orm/neon-http";
import { drizzle } from "drizzle-orm/neon-serverless";
import { drizzle } from "drizzle-orm/vercel-postgres";
import { drizzle } from "drizzle-orm/supabase";
import { drizzle } from "drizzle-orm/aws-data-api/pg";
import { drizzle } from "drizzle-orm/pglite";
// MySQL
import { drizzle } from "drizzle-orm/mysql2";
import { drizzle } from "drizzle-orm/planetscale-serverless";
import { drizzle } from "drizzle-orm/tidb-serverless";
// SQLite
import { drizzle } from "drizzle-orm/better-sqlite3";
import { drizzle } from "drizzle-orm/d1";
import { drizzle } from "drizzle-orm/libsql";
import { drizzle } from "drizzle-orm/bun-sqlite";
import { drizzle } from "drizzle-orm/expo-sqlite";
import { drizzle } from "drizzle-orm/op-sqlite";
import { drizzle } from "drizzle-orm/sql-js";
// Proxy drivers
import { drizzle } from "drizzle-orm/pg-proxy";
import { drizzle } from "drizzle-orm/mysql-proxy";
import { drizzle } from "drizzle-orm/sqlite-proxy";import { drizzle } from "drizzle-orm/node-postgres";
import { pgTable, serial, text, varchar } from "drizzle-orm/pg-core";
import { eq } from "drizzle-orm";
import { Pool } from "pg";
// Define schema
const users = pgTable("users", {
id: serial("id").primaryKey(),
name: text("name").notNull(),
email: varchar("email", { length: 255 }).unique(),
});
// Create database connection
const pool = new Pool({
connectionString: "postgresql://username:password@localhost:5432/db"
});
const db = drizzle(pool);
// Query data
const allUsers = await db.select().from(users);
const user = await db.select().from(users).where(eq(users.id, 1));
// Insert data
const newUser = await db.insert(users).values({
name: "John Doe",
email: "john@example.com"
}).returning();
// Update data
await db.update(users)
.set({ name: "Jane Doe" })
.where(eq(users.id, 1));Drizzle ORM is built around several key components:
pgTable, mysqlTable, sqliteTable for type-safe table structuresComprehensive schema definition system for creating type-safe database tables, columns, indexes, and constraints with support for PostgreSQL, MySQL, and SQLite-specific features.
function pgTable<TTableName extends string>(
name: TTableName,
columns: Record<string, AnyPgColumn>
): PgTable<{ name: TTableName; columns: typeof columns; }>;
function mysqlTable<TTableName extends string>(
name: TTableName,
columns: Record<string, AnyMySqlColumn>
): MySqlTable<{ name: TTableName; columns: typeof columns; }>;
function sqliteTable<TTableName extends string>(
name: TTableName,
columns: Record<string, AnySQLiteColumn>
): SQLiteTable<{ name: TTableName; columns: typeof columns; }>;Database connection management and driver configuration for all supported database providers with connection pooling, transactions, and runtime-specific optimizations.
function drizzle<TSchema extends Record<string, unknown>>(
client: NodePgClient,
config?: DrizzleConfig<TSchema>
): NodePgDatabase<TSchema>;
interface DrizzleConfig<TSchema extends Record<string, unknown>> {
schema?: TSchema;
logger?: Logger;
cache?: Cache;
}Type-safe query builders for all SQL operations with comprehensive support for complex queries, joins, subqueries, and database-specific features.
interface PgSelect<T> {
from<TTable extends AnyTable>(table: TTable): PgSelectWithTables<T, [TTable]>;
where(condition: SQL): this;
orderBy(...columns: (AnyColumn | SQL)[]): this;
limit(limit: number): this;
offset(offset: number): this;
}
interface PgInsert<T> {
values(values: T | T[]): this;
returning<TSelection>(selection?: TSelection): PgInsertReturning<TSelection>;
onConflictDoNothing(): this;
onConflictDoUpdate(config: { target: AnyColumn[], set: any }): this;
}Advanced ORM capabilities including schema migrations, query result caching, batch operations, relational queries, vector operations, and custom SQL expressions.
function migrate(
db: AnyPgDatabase,
config: MigrationConfig
): Promise<void>;
interface MigrationConfig {
migrationsFolder: string;
migrationsTable?: string;
migrationsSchema?: string;
}
function sql<T>(
strings: TemplateStringsArray,
...values: any[]
): SQL<T>;
function batch<T extends AnyDatabase>(db: T): BatchBuilder<T>;
function relations<T extends Record<string, AnyTable>>(
table: T,
config: RelationsConfig<T>
): Relations<T>;Powerful relational query system with automatic joins, nested results, and type-safe relationship definitions for complex data fetching patterns.
interface RelationalQueryBuilder<TSchema> {
[K in keyof TSchema]: TSchema[K] extends AnyTable
? TableRelationalQuery<TSchema[K], TSchema>
: never;
}
interface TableRelationalQuery<T extends AnyTable, TSchema> {
findFirst(config?: RelationalQueryConfig<T, TSchema>): Promise<InferSelectModel<T> | undefined>;
findMany(config?: RelationalQueryConfig<T, TSchema>): Promise<InferSelectModel<T>[]>;
}interface TableConfig<TColumn extends Column = Column<any>> {
name: string;
schema: string | undefined;
columns: Record<string, TColumn>;
dialect: string;
}
interface ColumnBaseConfig<TDataType extends ColumnDataType, TColumnType extends string> {
name: string;
dataType: TDataType;
columnType: TColumnType;
data: any;
driverParam: any;
notNull: boolean;
hasDefault: boolean;
enumValues: any[];
}
type ColumnDataType = 'string' | 'number' | 'boolean' | 'date' | 'json' | 'buffer' | 'array' | 'bigint' | 'custom';
type Chunk = string | Table | Column | SQL;
interface Table<T extends TableConfig = TableConfig> extends SQLWrapper {
readonly [Table.Symbol.Name]: T['name'];
readonly [Table.Symbol.Schema]: T['schema'];
readonly [Table.Symbol.Columns]: T['columns'];
}
interface Column<T extends ColumnBaseConfig<ColumnDataType, string> = ColumnBaseConfig<ColumnDataType, string>> extends SQLWrapper {
readonly name: T['name'];
readonly dataType: T['dataType'];
readonly columnType: T['columnType'];
readonly notNull: T['notNull'];
readonly hasDefault: T['hasDefault'];
}
interface SQL<T = unknown> extends SQLWrapper {
readonly queryChunks: Chunk[];
getSQL(): SQL<T>;
}
interface SQLWrapper {
getSQL(): SQL;
}
type AnyColumn = Column<any>;
type AnyTable = Table<any>;
type AnyPgColumn = Column<ColumnBaseConfig<any, 'PgColumn'>>;
type AnyMySqlColumn = Column<ColumnBaseConfig<any, 'MySqlColumn'>>;
type AnySQLiteColumn = Column<ColumnBaseConfig<any, 'SQLiteColumn'>>;
// Database-specific table types
interface PgTable<T extends TableConfig = TableConfig> extends Table<T> {}
interface MySqlTable<T extends TableConfig = TableConfig> extends Table<T> {}
interface SQLiteTable<T extends TableConfig = TableConfig> extends Table<T> {}
// Database connection types
type NodePgClient = any; // pg.Pool | pg.Client
type MySqlClient = any; // mysql2.Connection | mysql2.Pool
type SQLiteClient = any; // Database instance
// Database instance types
interface NodePgDatabase<TSchema extends Record<string, unknown> = Record<string, never>> {
select(): any;
insert<T extends AnyTable>(table: T): any;
update<T extends AnyTable>(table: T): any;
delete<T extends AnyTable>(table: T): any;
query: TSchema extends Record<string, never> ? never : any;
}
interface MySqlDatabase<TSchema extends Record<string, unknown> = Record<string, never>> {
select(): any;
insert<T extends AnyTable>(table: T): any;
update<T extends AnyTable>(table: T): any;
delete<T extends AnyTable>(table: T): any;
query: TSchema extends Record<string, never> ? never : any;
}
interface SQLiteDatabase<TSchema extends Record<string, unknown> = Record<string, never>> {
select(): any;
insert<T extends AnyTable>(table: T): any;
update<T extends AnyTable>(table: T): any;
delete<T extends AnyTable>(table: T): any;
query: TSchema extends Record<string, never> ? never : any;
}
// Configuration types
interface DrizzleConfig<TSchema extends Record<string, unknown>> {
schema?: TSchema;
logger?: Logger | boolean;
cache?: Cache;
casing?: any;
}
interface Logger {
logQuery(query: string, params: unknown[]): void;
}
interface Cache {
get<T>(key: string): Promise<T | null>;
set(key: string, value: unknown, ttl?: number): Promise<void>;
delete(key: string): Promise<void>;
clear(): Promise<void>;
}
interface MigrationConfig {
migrationsFolder: string;
migrationsTable?: string;
migrationsSchema?: string;
}