What’s New

Drizzle ORM

Frameworks & Libraries

A TypeScript ORM that stays close to SQL, for SQL-friendly schemas and queries.

Latest 0.45.2 · by Drizzle TeamWebsitedrizzle-team/drizzle-orm

Changelog

v1.0.0-rc.4

Pre-release
Added 13
  • Supported nested transactions in @tursodatabase/database and @tursodatabase/database-wasm
  • Filesystem-less migrator for @tursodatabase/database-wasm at drizzle-orm/tursodatabase/wasm-migrator
  • Codec system to mysql
  • Added @tursodatabase/serverless driver support
  • Added @tursodatabase/sync driver support
  • Added @effect/sql-pglite driver support
Changed 10
  • Updated SQLite db.$count builder to include .sync() executor for sync drivers
  • Switched sqlite RQBv2 to array mode
  • Enabled optimized default query mappers for sqlite
  • Reworked sqlite sessions to replace per-driver PreparedQuery instances with executors passed via sessions
  • Split SQLite into async and effect versions with sync as subtype of async
  • Split mysql into async and effect versions
Fixed 19
  • View types when using Subquery in selection
  • Custom types' JSON field API not being applied when column is used as a decoder on SQL fields
  • Codecs not getting applied to SQL field when .mapWith(column) is set
  • Subquery fields' columns' codecs not being applied to subquery
  • Broken db.select in bun-sql/pg driver
  • Instances of sqlite query errors not being wrapped in DrizzleQueryError
Removed 3
  • RQBv1 from sqlite and RQBv1 TSchema, TFullSchema arguments from sqlite entities' generics
  • mapResult method from PreparedQuery interface and mapResult, mapBatchResult from pg and sqlite raw queries
  • SQLiteSyncDialect and SQLiteAsyncDialect, moved generic SQLite async/sync migrators to sqlite-core/async/session

v1.0.0-rc.4

  • Fixed broken View types when using Subquery in selection
  • Fixed custom types' JSON field API not being applied when column is used as a decoder on SQL fields
  • Fixed codecs not getting applied to SQL field when .mapWith(column) is set (fixes #5724)
  • Fixed Subquery fields' columns' codecs not being applied to subquery
  • Fixed broken in rc.3 db.select in bun-sql/pg driver (fixes #5779)
  • Updated SQLite db.$count builder to include .sync() executor for sync drivers
  • Removed RQBv1 from sqlite, removed RQBv1 TSchema, TFullSchema arguments from sqlite entities' generics
  • Fixed instances of sqlite query errors not being wrapped in DrizzleQueryError (db.batch() excluded due to api incompatibility)
  • Fixed type error on CockroachArrayBuilder constructor caused by referencing internal field's type
  • Removed mapResult method from PreparedQuery interface, removed mapResult, mapBatchResult from pg and sqlite raw queries
  • Fixed wrong bun-sqlite run result type
  • Switched sqlite RQBv2 to array mode
  • Enabled optimized default query mappers for sqlite
  • Reworked sqlite sessions: replaced per-driver PreparedQuery instances with executors passed via sessions, similar to current postgresql and mysql implementations, moved useJitMappers flag handling to dialect
  • Fixed missing string overload on .comment(sqlCommenterComment) in query builders
  • Supported nested transactions in @tursodatabase/database, @tursodatabase/database-wasm
  • Added filesytem-less migrator for @tursodatabase/database-wasm at drizzle-orm/tursodatbase/wasm-migrator
  • Split SQLite into async, effect versions (sync remains subtype of async)
  • Removed SQLiteSyncDialect, SQLiteAsyncDialect, moved generic SQLite async\sync migrators to sqlite-core/async/session as migrateSync, migrateAsync
  • Fixed sqlite cache using same cache entry for different execute methods
  • Moved EffectDrizzlePgConfig to drizzle-orm/pg-core/effect/utils
  • Made cache field in EffectCacheShape optional
  • Split mysql into async, effect versions
  • Added codec system to mysql
  • Fixed mysql float rounding to either 6 digits or double
  • Fixed mysql cropping .000 from timestamp(3)
  • Moved subquery mapper selection from dialect.buildSelection to orderSelectedFields;
  • [PG, MySQL] Improved codec system in set operators:
    • When different db types are crossed in a union, db casts them to type it deems as closest compatible to all types involved
    • If columns with codecs are set on both sides of union - codec of combined type will apply
    • If only the left-hand side of union has field with codec - left hand side's codec is preserved
    • If left-hand side field is devoid of codecs - field is not processed by codecs;
    • Set operator queries are switched from [QUERY 1] UNION [QUERY 2] to SELECT ... FROM ([QUERY 1] UNION [QUERY 2]) "drizzle_union" so cast codecs would apply after union's type mutation
    • Retrieved data of union with different types still may be lossy due to db's own conversion
  • Bump required effect package versions to 4.0.0-beta.83
  • Fixed sql.param passing Placeholder as expected input value to encoder function instead of Placeholder's value type
  • Fixed unguarded Buffer reference in drizzle-orm/effect-schema that caused error in environments without Buffer
  • Fixed sqlite blob column runtime-type default mode mismatch (fixes #1064)
  • Improved typed sql operator - preserved nullability, inferred initial data type to mapWithcallback argument, added .nullable() method to modify output type with | null (fixes #571):
      // Before:
      sql<Type | null>`...`.mapWith((v: any) => String(v)) // Output type: string
      // After:
      sql<Type | null>`...`.mapWith((v: Type) => String(v)) // Output type: string | null
      // `.nullable()` method:
      sql`...`.mapWith((v: unknown) => new Type(v)).nullable() // Output type: Type | null
    
  • Fixed generatedByDefaultAsIdentity columns not being filtered from inserts in runtime in postgres dialect
  • Improved db.insert(table).select(...): removed column order match requirement, allowed skipping selection for columns with defaults or nullability (fixes #3608)
Drivers
  • Updated @tursodatabase/database, @tursodatabase/database-wasm to v0.6.0, updated session internals for asynchronous prepare on driver side

  • Added @tursodatabase/serverless driver support

  • Added @tursodatabase/sync driver support

  • Added @effect/sql-pglite driver support

  • Added @effect/sql-sqlite-node driver support

  • Added @effect/sql-sqlite-bun driver support

  • Added @effect/sql-sqlite-do driver support

  • Added @effect/sql-sqlite-wasm driver support

  • Added @effect/sql-libsql driver support

  • Added @effect/sql-d1 driver support

  • Added @effect/sql-mysql2 driver support

  • Fixed @effect/sql-pg driver returning object response instead of raw response on db.execute

  • pg-proxy: added dialect config to optional dialect creator callback

  • Fixed postgres pull from failing for non-admin roles (fixes #5568)

  • Fixed: [BUG]: [mssql] INSERT includes generatedAlwaysAs (computed) columns in the column list — SQL Server error 271

Drizzle Kit
Machine-readable output & programmatic SDK
  • Added an --output text|json mode to generate, push, pull, up, export, and check. In json mode each command emits a typed JSON envelope (status, errors, payloads) for programmatic and agent consumption (see OUTPUT_MODES.md, JSON_CONTRACT.md)
  • Shipped a public programmatic SDK at the drizzle-kit/cli subpath exposing generate(), push(), pull(), up(), exportSql(), and check() with typed options and results matching the CLI JSON contract (see SDK.md)
  • Auto-detected non-interactive mode (--output json, or --output text with a non-TTY stdin) no longer renders interactive prompts. Instead, unresolved renames and destructive changes (confirm_data_loss) are surfaced as a missing_hints envelope (or a missing-decisions report under text) and resolved by supplying a structured hints array up front via --hints / --hints-file (see HINTS.md)
MCP server
  • Added drizzle-kit mcp, a Model Context Protocol server over stdio that exposes the migration lifecycle (generate, push, check, export, up, pull) as MCP tools for any MCP-capable AI agent (see MCP.md)
Agent skills
  • Added drizzle-kit skills, which installs Drizzle Kit's bundled Agent Skills into your project for AI coding assistants. Ships 8 skills: drizzle, drizzle-generate, drizzle-hints, drizzle-migrations, drizzle-output-modes, drizzle-pull, drizzle-push, and drizzle-responses-and-errors (see drizzle-kit/skills folder)

v1.0.0-rc.3

Pre-release

v1.0.0-rc.3

Porting all the changes that were made in PostgreSQL to other dialects. This release is about MySQL:

  • Removed RQBv1 from mysql dialect (._query)
  • Internal MySQL sessions refactoring and moving to a unified query preparation function
  • Fallback to regular queries on iterators for drivers that don't support streaming instead of throwing an error for compatibility
  • Enabled optimized non-jit mappers for regular queries for MySQL dialect
  • Switched RQBv2 to array mode querying, disabled root query level JSON conversions
  • Fixed MySQL proxy driver not using lastInsertId, affectedRows from dedicated response fields

Next releases will include:

  • Effect MySQL support
  • SQLite rework (same as this release for MySQL)
  • SQLite Effect Support

v1.0.0-rc.2

Pre-release
Updates
  • Disabled default codec type selectors for custom columns (fixes #5711)
  • Сallback type overload for codec selector in custom pg columns (codec: (config) => config?.withTimeZone ? 'timestamptz' : 'timestamp')
  • Extended list of postgis types for codecs (improvement for #5711)
  • Updated codecs: geometry -> geometry(point), geometry:tuple -> geometry(point):tuple
  • Switched PG transactions from class properties back to class methods (fixes #5709)
  • Updated AWS Data Api codecs, removed query typings, improved input param mapping
  • Removed prepared query typings field from all builders
  • Added column argument to CastParam,CastArrayParam codecs
Migration updates in SQLite
  • Added migration conflict detection for SQLite. When migration history has multiple open branches, drizzle-kit generate now checks whether those branches can be merged safely before creating the next migration. This helps catch cases where two migrations were created from the same parent and then changed the same SQLite object in incompatible ways, for example two branches changing the same table, index, or view.
npx drizzle-kit generate
  • If the conflict is expected and you want to continue anyway, pass --ignore-conflicts to skip the conflict check for that command.
npx drizzle-kit generate --ignore-conflicts
npx drizzle-kit check --ignore-conflicts
  • Added proper SQLite migration tree merging. New snapshots now collect all open leaf snapshot IDs and write them as parents, instead of keeping only one latest parent. This means a new migration generated after branching can merge all open leaves and use the combined SQLite state for the next snapshot diff.
{
  "prevIds": ["first-open-leaf-id", "second-open-leaf-id"]
}
  • Fixed DrizzleQueryError and TransactionRollbackError constructors to properly set the error name for better instanceof checks
  • Fixed error handling in aws-data-api to properly show database error messages

v1.0.0-rc.1

Pre-release

v1.0.0-rc.1

⚠️ This release introduced a breaking change into our casing API(see below) and removes RQB v1 ._query for postgres

JIT mappers

Drizzle ORM now has an opt-in API for JIT(just in time compilated) mappers which make most expensive part of the db request pipeline(row mapping) as fast as humanly possible.

const db = drizzle({ ..., jit: true })

const query = db.select().from(users).prepare();
// ^ here drizzle generates a jit mapper which will then be reused during each invocation

server.get('users', (c) => {
  const users = await query.execute(); // as fast as using raw driver
  return c.json(users)
})

We've reworked internals of Drizzle ORM with the new system of codecs. Those are now in charge of normalising responses and requests for diffrent drivers across pg dialect. They helped us not only properly fix a set of data mapping issues but also massively improve performance by not doing unnecessary work. We've seen a 25%-30% reduction in latency, while +800rps(14500->15300) in our benchmarks Give it a go and let us know if everything works just fine!

Effect v4

drizzle-orm@1.0.0-rc.1 comes with native support for Effect v4 via:

import { PgClient } from '@effect/sql-pg';
import * as PgDrizzle from 'drizzle-orm/effect-postgres';
import * as Effect from 'effect/Effect';
import * as Redacted from 'effect/Redacted';
import { relations } from '../relations';

const connectionStr = Redacted.make(process.env['PG_CONNECTION_STRING']!);
const PgClientLive = PgClient.layer({
  url: connectionStr,
});

const DB = PgDrizzle.make({ relations }).pipe(Effect.provide(PgDrizzle.DefaultServices));
const program = Effect.gen(function*() {
  const db = yield* DB;

  const users = yield* db.select().from(usersTable);
}).pipe(Effect.provide(PgClientLive));

await Effect.runPromise(program);
New Casing API

⚠️ BREAKING CHANGE In rc.1 we've finally reworked our legacy casing API of const db = drizzle({..., casing: "camel" }) which turned out to not be a proper solution, it required duplication in drizzle-orm instantiation and drizzle-kit config and introduced and set of endless bugs all around query builder chain. All of the above is now fixed with new API:

import * as d from "drizzle-orm/pg-core";

const users = d.snakeCase.table("users", {
  id: d.serial().primaryKey(),
  email: d.text().unique(),
  fullName: d.text(), // full_name in db
  createdAt: d.timestamp().defaultNow(), // created_at in db
})

// --- for namespaces/schemas you can use

const schema2 = d.camelCase.schema("schema2");

const usersInSchema2 = schema2.table("users", ...);
const ordersInSchema2 = schema2.table("orders", ...);
// ^ all entities in schema2 will be snake_cased


// --- all available entities
import { snakeCase, camelCase } from "drizzle-orm/pg-core";

snakeCase.view
snakeCase.materializedView
snakeCase.schema
snakeCase.table

camelCase.view
camelCase.materializedView
camelCase.schema
camelCase.table
New Netlify Database Driver

Note: The Netlify Database driver is developed and maintained by the Netlify team.

Installation:

npm install @netlify/database

Usage example:

import { drizzle } from 'drizzle-orm/netlify-db';

const db = drizzle();

const result = await db.execute('select 1');
import { drizzle } from 'drizzle-orm/netlify-db';

const db = drizzle(process.env.DATABASE_URL);

const result = await db.execute('select 1');
import { drizzle } from 'drizzle-orm/netlify-db';

// Explicit client — consumer controls the driver
const db = drizzle({ client: netlifyDbClient });

const result = await db.execute('select 1');
Bug fixes and improvements:
  • Codec system for postgres - resolves issues created by differences of data types returned by different drivers or different contexts of query (regular select, JSON object, postgres array). Currently only handles supported by drizzle constructors column types. (fixes #3018, #5090, #5287)
  • Optimized query mappers for postgres
  • Opt-in JIT-generated mappers for all dialects
  • Optimized RQBv2 mappers for all dialects
  • ⚠️ BREAKING CHANGE: Removed RQBv1 (db._query) from postgres
  • Moved pg array utils (makePgArray, parsePgArray) from drizzle-orm/pg-core/utils[/array] to drizzle-orm/pg-core/array
  • Simplified postgres sessions & prepared queries
  • Fixed neon-http bytea data corruption
  • Fixed bun-sql/postgres timestamp timezone truncation, json[b] data double stringification
  • ⚠️ BREAKING CHANGE: Reworked casing API - moved casing control from db instance to table \ view \ schema via import { snakeCase, camelCase } from "drizzle-orm/dialect-core", fixed #5112 #5282 #4181 #4209
  • Switched from Effect V3 to Effect V4 beta for effect-schema, effect-postgres (fixes #5414)

v1.0.0-beta.22

Pre-release
Bug fixed
v1.0.0-beta.21Pre-release

1.0.0-beta.21

More fixes for the drizzle-kit migration process and commutativity checks

  • Adding a value to a PostgreSQL enum will no longer be treated as commutative
  • Enum values added in different leaves will now be merged properly
v1.0.0-beta.20Pre-release

1.0.0-beta.20

  • Fixed sql.identifier(), sql.as() escaping issues. Previously all the values passed to this functions were not properly escaped causing a possible SQL Injection (CWE-89) vulnerability

Thanks to @EthanKim88, @0x90sh and @wgoodall01 for reaching out to us with a reproduction and suggested fix

0.45.2

  • Fixed sql.identifier(), sql.as() escaping issues. Previously all the values passed to this functions were not properly escaped causing a possible SQL Injection (CWE-89) vulnerability

Thanks to @EthanKim88, @0x90sh and @wgoodall01 for reaching out to us with a reproduction and suggested fix

v1.0.0-beta.19

Pre-release
New Features
sqlcommenter support for PostgreSQL and MySQL

You can now add custom tags to the query. These tags will be appended to the end of each query, helping the database add metadata/tags to it. This will be especially useful with PlanetScale’s new Database Traffic Control feature

// raw string support
db.select().from().comment("key='val'");
db.select().from().comment("my_first_tag");

// developer friendly dedicated to tags
db.select().from().comment({ key: 'val' });

Example:

db.select().from(comments).comment({ priority: 'high', category: "analytics" });
select "id", "name" from "comments" /*priority='high',category='analytics'*/

The only limitation is that you can't use comments with a prepared statement:

// can't be used
const p = db.select().from().prepare();
// ❌
p.comment({ key: 'val' }).execute();
Bug fixes
Updates
  • Updated migrate() function for mysql dialect to correctly manage multiple databases

  • The behavior for reading schema files has been updated. From now only files with the following extensions will be processed: .js .mjs .cjs .jsx .ts .mts .cts .tsx. All other file types will be ignored

v1.0.0-beta.18

Pre-release
New driver support for kit and studio

You can now use the node:sqlite driver to run migrations and browse Drizzle Studio. If node:sqlite is available at runtime, we will automatically detect it and use it.

Fixes

Discussion