opción
HogarHogar Skill Desarrollo web drizzle-orm

ORM de SQL con seguridad de tipos para TypeScript sin ninguna sobrecarga en tiempo de ejecución

...Expandir todo
70
Tiempo actualizado 29 de junio de 2026

Acerca de drizzle-orm

Drizzle ORM es una biblioteca moderna de mapeo objeto-relacional (ORM) basada en TypeScript, diseñada para proporcionar interacciones seguras en cuanto a tipos con bases de datos SQL, sin generar ninguna sobrecarga en tiempo de ejecución. Resuelve el problema habitual de los errores en tiempo de ejecución y la falta de coincidencia de tipos al trabajar con bases de datos relacionales, ofreciendo una comprobación de tipos en tiempo de compilación y una sintaxis similar a la de SQL que los desarrolladores pueden utilizar directamente en TypeScript. Esto hace que las operaciones con bases de datos sean más predecibles y reduce la probabilidad de que se produzcan errores en entornos de ejecución sin servidor o en el borde, donde la eficiencia y las dependencias mínimas son fundamentales.

El ORM ofrece varias características y capacidades clave. Es compatible con múltiples bases de datos, entre ellas PostgreSQL, MySQL y SQLite, lo que permite a los desarrolladores elegir el controlador adecuado para su proyecto. Drizzle ORM proporciona un sistema flexible de definición de esquemas con una variedad de tipos de columna mapeados directamente a tipos de TypeScript, lo que permite un tipado fuerte para consultas, inserciones y actualizaciones. También incluye funciones para definir relaciones entre tablas, como las relaciones uno a muchos, y admite la inferencia de tipos tanto para operaciones de selección como de inserción. Además, Drizzle Kit puede utilizarse para migraciones, lo que facilita la gestión de los cambios en el esquema de la base de datos a lo largo del tiempo. Su diseño sin dependencias garantiza una integración ligera en los proyectos y un rendimiento óptimo en entornos con restricciones.

Entre los usuarios a los que va dirigido se encuentran los desarrolladores de TypeScript que crean aplicaciones que interactúan con bases de datos SQL y requieren una seguridad de tipos fuerte y un comportamiento predecible. Drizzle ORM resulta especialmente útil para quienes desarrollan aplicaciones sin servidor, funciones de borde o proyectos en los que el rendimiento y una sobrecarga mínima en tiempo de ejecución son importantes. Es adecuado para escenarios que van desde sencillas aplicaciones CRUD hasta sistemas más complejos con modelos de datos relacionales y patrones de consulta avanzados, proporcionando un enfoque fiable y fácil de mantener para las interacciones con bases de datos, al tiempo que aprovecha el sistema de tipos de TypeScript.

Preguntas frecuentes

¿Cómo se instala y se configura Drizzle ORM?

Puedes instalar el ORM principal mediante npm con `npm install drizzle-orm` y, a continuación, instalar el controlador adecuado para tu base de datos, como `pg` para PostgreSQL o `mysql2` para MySQL. Para las migraciones, instala `drizzle-kit` como dependencia de desarrollo.

¿Qué bases de datos son compatibles con Drizzle ORM?

Drizzle ORM es compatible con PostgreSQL, MySQL y SQLite a través de sus respectivos controladores de base de datos.

¿Añade Drizzle ORM sobrecarga en tiempo de ejecución?

No, Drizzle ORM está diseñado sin sobrecarga en tiempo de ejecución, basándose en la comprobación de tipos en tiempo de compilación para garantizar la seguridad y la corrección.

¿Puedo definir relaciones entre tablas?

Sí, Drizzle ORM permite definir relaciones como «uno a muchos», lo que te permite modelar datos relacionales en TypeScript de forma segura.

¿Es Drizzle ORM adecuado para entornos sin servidor o de borde?

Sí, está optimizado para ofrecer un buen rendimiento en entornos sin servidor y de perímetro gracias a su diseño sin dependencias y a su eficiente gestión de consultas.

Ver en GitHub

Drizzle ORM

Modern TypeScript-first ORM with zero dependencies, compile-time type safety, and SQL-like syntax. Optimized for edge runtimes and serverless environments.

Quick Start

Installation

# Core ORMnpm install drizzle-orm# Database driver (choose one)npm install pg            # PostgreSQLnpm install mysql2        # MySQLnpm install better-sqlite3 # SQLite# Drizzle Kit (migrations)npm install -D drizzle-kit

Basic Setup

// db/schema.tsimport { pgTable, serial, text, timestamp } from 'drizzle-orm/pg-core';export const users = pgTable('users', {  id: serial('id').primaryKey(),  email: text('email').notNull().unique(),  name: text('name').notNull(),  createdAt: timestamp('created_at').defaultNow(),});// db/client.tsimport { drizzle } from 'drizzle-orm/node-postgres';import { Pool } from 'pg';import * as schema from './schema';const pool = new Pool({ connectionString: process.env.DATABASE_URL });export const db = drizzle(pool, { schema });

First Query

import { db } from './db/client';import { users } from './db/schema';import { eq } from 'drizzle-orm';// Insertconst newUser = await db.insert(users).values({  email: '[email protected]',  name: 'John Doe',}).returning();// Selectconst allUsers = await db.select().from(users);// Whereconst user = await db.select().from(users).where(eq(users.id, 1));// Updateawait db.update(users).set({ name: 'Jane Doe' }).where(eq(users.id, 1));// Deleteawait db.delete(users).where(eq(users.id, 1));

Schema Definition

Column Types Reference

PostgreSQLMySQLSQLiteTypeScript
serial()serial()integer()number
text()text()text()string
integer()int()integer()number
boolean()boolean()integer()boolean
timestamp()datetime()integer()Date
json()json()text()unknown
uuid()varchar(36)text()string

Common Schema Patterns

import { pgTable, serial, text, varchar, integer, boolean, timestamp, json, unique } from 'drizzle-orm/pg-core';export const users = pgTable('users', {  id: serial('id').primaryKey(),  email: varchar('email', { length: 255 }).notNull().unique(),  passwordHash: varchar('password_hash', { length: 255 }).notNull(),  role: text('role', { enum: ['admin', 'user', 'guest'] }).default('user'),  metadata: json('metadata').$type<{ theme: string; locale: string }>(),  isActive: boolean('is_active').default(true),  createdAt: timestamp('created_at').defaultNow().notNull(),  updatedAt: timestamp('updated_at').defaultNow().notNull(),}, (table) => ({  emailIdx: unique('email_unique_idx').on(table.email),}));// Infer TypeScript typestype User = typeof users.$inferSelect;type NewUser = typeof users.$inferInsert;

Relations

One-to-Many

import { pgTable, serial, text, integer } from 'drizzle-orm/pg-core';import { relations } from 'drizzle-orm';export const authors = pgTable('authors', {  id: serial('id').primaryKey(),  name: text('name').notNull(),});export const posts = pgTable('posts', {  id: serial('id').primaryKey(),  title: text('title').notNull(),  authorId: integer('author_id').notNull().references(() => authors.id),});export const authorsRelations = relations(authors, ({ many }) => ({  posts: many(posts),}));export const postsRelations = relations(posts, ({ one }) => ({  author: one(authors, {    fields: [posts.authorId],    references: [authors.id],  }),}));// Query with relationsconst authorsWithPosts = await db.query.authors.findMany({  with: { posts: true },});

Many-to-Many

export const users = pgTable('users', {  id: serial('id').primaryKey(),  name: text('name').notNull(),});export const groups = pgTable('groups', {  id: serial('id').primaryKey(),  name: text('name').notNull(),});export const usersToGroups = pgTable('users_to_groups', {  userId: integer('user_id').notNull().references(() => users.id),  groupId: integer('group_id').notNull().references(() => groups.id),}, (table) => ({  pk: primaryKey({ columns: [table.userId, table.groupId] }),}));export const usersRelations = relations(users, ({ many }) => ({  groups: many(usersToGroups),}));export const groupsRelations = relations(groups, ({ many }) => ({  users: many(usersToGroups),}));export const usersToGroupsRelations = relations(usersToGroups, ({ one }) => ({  user: one(users, { fields: [usersToGroups.userId], references: [users.id] }),  group: one(groups, { fields: [usersToGroups.groupId], references: [groups.id] }),}));

Queries

Filtering

import { eq, ne, gt, gte, lt, lte, like, ilike, inArray, isNull, isNotNull, and, or, between } from 'drizzle-orm';// Equalityawait db.select().from(users).where(eq(users.email, '[email protected]'));// Comparisonawait db.select().from(users).where(gt(users.id, 10));// Pattern matchingawait db.select().from(users).where(like(users.name, '%John%'));// Multiple conditionsawait db.select().from(users).where(  and(    eq(users.role, 'admin'),    gt(users.createdAt, new Date('2024-01-01'))  ));// IN clauseawait db.select().from(users).where(inArray(users.id, [1, 2, 3]));// NULL checksawait db.select().from(users).where(isNull(users.deletedAt));

Joins

import { eq } from 'drizzle-orm';// Inner joinconst result = await db  .select({    user: users,    post: posts,  })  .from(users)  .innerJoin(posts, eq(users.id, posts.authorId));// Left joinconst result = await db  .select({    user: users,    post: posts,  })  .from(users)  .leftJoin(posts, eq(users.id, posts.authorId));// Multiple joins with aggregationimport { count, sql } from 'drizzle-orm';const result = await db  .select({    authorName: authors.name,    postCount: count(posts.id),  })  .from(authors)  .leftJoin(posts, eq(authors.id, posts.authorId))  .groupBy(authors.id);

Pagination & Sorting

import { desc, asc } from 'drizzle-orm';// Order byawait db.select().from(users).orderBy(desc(users.createdAt));// Limit & offsetawait db.select().from(users).limit(10).offset(20);// Pagination helperfunction paginate(page: number, pageSize: number = 10) {  return db.select().from(users)    .limit(pageSize)    .offset(page * pageSize);}

Transactions

// Auto-rollback on errorawait db.transaction(async (tx) => {  await tx.insert(users).values({ email: '[email protected]', name: 'John' });  await tx.insert(posts).values({ title: 'First Post', authorId: 1 });  // If any query fails, entire transaction rolls back});// Manual controlconst tx = db.transaction(async (tx) => {  const user = await tx.insert(users).values({ ... }).returning();  if (!user) {    tx.rollback();    return;  }  await tx.insert(posts).values({ authorId: user.id });});

Migrations

Drizzle Kit Configuration

// drizzle.config.tsimport type { Config } from 'drizzle-kit';export default {  schema: './db/schema.ts',  out: './drizzle',  dialect: 'postgresql',  dbCredentials: {    url: process.env.DATABASE_URL!,  },} satisfies Config;

Migration Workflow

# Generate migrationnpx drizzle-kit generate# View SQLcat drizzle/0000_migration.sql# Apply migrationnpx drizzle-kit migrate# Introspect existing databasenpx drizzle-kit introspect# Drizzle Studio (database GUI)npx drizzle-kit studio

Example Migration

-- drizzle/0000_initial.sqlCREATE TABLE IF NOT EXISTS "users" (  "id" serial PRIMARY KEY NOT NULL,  "email" varchar(255) NOT NULL,  "name" text NOT NULL,  "created_at" timestamp DEFAULT now() NOT NULL,  CONSTRAINT "users_email_unique" UNIQUE("email"));

Navigation

Detailed References

  • 🏗️ Advanced Schemas - Custom types, composite keys, indexes, constraints, multi-tenant patterns. Load when designing complex database schemas.

  • 🔍 Query Patterns - Subqueries, CTEs, raw SQL, prepared statements, batch operations. Load when optimizing queries or handling complex filtering.

  • ⚡ Performance - Connection pooling, query optimization, N+1 prevention, prepared statements, edge runtime integration. Load when scaling or optimizing database performance.

  • 🔄 vs Prisma - Feature comparison, migration guide, when to choose Drizzle over Prisma. Load when evaluating ORMs or migrating from Prisma.

Red Flags

Stop and reconsider if:

  • Using any or unknown for JSON columns without type annotation
  • Building raw SQL strings without using sql template (SQL injection risk)
  • Not using transactions for multi-step data modifications
  • Fetching all rows without pagination in production queries
  • Missing indexes on foreign keys or frequently queried columns
  • Using select() without specifying columns for large tables

Performance Benefits vs Prisma

MetricDrizzlePrisma
Bundle Size~35KB~230KB
Cold Start~10ms~250ms
Query SpeedBaseline~2-3x slower
Memory~10MB~50MB
Type GenerationRuntime inferenceBuild-time generation

Integration

  • typescript-core: Type-safe schema inference with satisfies
  • nextjs-core: Server Actions, Route Handlers, Middleware integration
  • Database Migration: Safe schema evolution patterns

Related Skills

When using Drizzle, these skills enhance your workflow:

  • prisma: Alternative ORM comparison: Drizzle vs Prisma trade-offs
  • typescript: Advanced TypeScript patterns for type-safe queries
  • nextjs: Drizzle with Next.js Server Actions and API routes
  • sqlalchemy: SQLAlchemy patterns for Python developers learning Drizzle

[Full documentation available in these skills if deployed in your bundle]

Instalar drizzle-orm

Descarga y descomprime los archivos de las habilidades en tu directorio .claude/skills/.

Descargar ZIP

Clona el repositorio y copia los archivos de la habilidad a tu proyecto.

git clone https://github.com/bobmatnyc/claude-mpm-skills/blob/main/toolchains/typescript/data/drizzle/SKILL.md # Copy SKILL.md to your .claude/skills/ directory

Copiar Copiar
Configuración rápida: Copia la carpeta de la habilidad en .claude/skills/. Claude la detectará automáticamente y la utilizará.

Habilidades relacionadas

github-code-search
Tiempo actualizado 29 de junio de 2026
clickhouse-io
Tiempo actualizado 29 de junio de 2026
prisma-client-api
Tiempo actualizado 29 de junio de 2026
coding-standards
Tiempo actualizado 29 de junio de 2026
OR