PostgreSQL + Drizzle ORM: mi stack favorito para proyectos con IA
Cómo Drizzle ORM transformó mi desarrollo backend en proyectos de IA con TypeScript, tipos seguros y rendimiento de producción.
Mario Inostroza
PostgreSQL + Drizzle ORM se ha convertido en mi stack backend preferido para proyectos de IA. No es solo otra ORM — es un cambio de paradigma que resolvió problemas críticos en mi flujo de desarrollo.
El problema: Prisma en un mundo de IA
Cuando empecé con Examya, usaba Prisma. Y funciona bien para apps CRUD estándar. Pero en IA, las cosas son diferentes:
- Los datos cambian constantemente: embeddings, vectores, JSON complejo
- Las relaciones no son siempre claras entre entidades
- Los modelos de datos evolucionan con cada iteración
- La performance en queries complejas es crítica
Prisma, con su enfoque en tipos estáticos y migraciones explícitas, se volvió un cuello de botella. Cada cambio de schema requería:
- Escribir migración manual
- Regenerar el cliente
- Actualizar todos los types
- Asegurar compatibilidad con datos existentes
En un entorno ágil de IA, esto era demasiado lento.
La solución: Drizzle ORM
Drizzle cambia el juego con su enfoque en tiempo de desarrollo vs tiempo de ejecución. No es solo “Prisma pero más rápido” — es un diseño completamente diferente.
Tipos inferidos en tiempo de desarrollo
Drizzle no requiere generar tipos. TypeScript infiere todo desde el schema en tiempo de desarrollo:
// Esto funciona sin npx prisma generate
const users = await db.select().from(users).where(eq(users.age, 30))
Esto significa que puedo cambiar mi schema y ver los errores de TypeScript inmediatamente — sin esperar a generar el cliente.
Queries más expresivas
La API de Drizzle es más natural para queries complejas:
// Prisma requería múltiples .include()
const orders = await db.query.orders.findMany({
where: eq(orders.status, 'paid'),
with: {
user: {
where: gt(users.createdAt, new Date('2024-01-01'))
},
items: {
where: not(items.price.isNull())
}
}
})
// Drizzle permite nesting más natural
const orders = await db
.select()
.from(orders)
.leftJoin(users, eq(orders.userId, users.id))
.where(and(
eq(orders.status, 'paid'),
gt(users.createdAt, new Date('2024-01-01'))
))
Performance de producción
Drizzle usa “query builders” que se compilan a SQL optimizado. En Examya, donde tengo queries que procesan miles de órdenes diarias, la diferencia es significativa:
- Menos memoria RAM por query
- Generación de SQL más rápida
- Caching inteligente de conexiones
Integración con IA
Almacenamiento de embeddings con pgvector
Drizzle maneja perfectamente pgvector, que es crucial para IA:
// Definición del schema con soporte para vectores
export const embeddings = pgTable('embeddings', {
id: serial('id').primaryKey(),
content: text('content').notNull(),
embedding: vector('embedding', { dimensions: 1536 }).notNull(),
metadata: json('metadata').default('{}'),
createdAt: timestamp('created_at').defaultNow()
})
// Query de similitud semántica
const similar = await db
.select()
.from(embeddings)
.where(
sql`embedding <=> ${embedding} < 0.3`
)
.limit(5)
Manejo de datos complejos
Los agentes de IA generan datos estructurados pero impredecibles:
// Drizzle maneja JSON naturalmente
export const agentContexts = pgTable('agentContexts', {
id: serial('id').primaryKey(),
session: text('session').notNull(),
context: json('context').$type<Record<string, any>>(),
metadata: json('metadata').$type<AgentMetadata>(),
lastUsed: timestamp('last_used').defaultNow()
})
// Consultas flexibles
const sessionData = await db
.select()
.from(agentContexts)
.where(
jsonContains(agentContexts.context, { agent: 'shuri' })
)
Caso real: Examya
Decisión técnica
Para el backend de Examya, elegí:
- PostgreSQL: La consistencia ACID es no negociable para datos médicos
- Drizzle ORM: Flexibilidad para evolución rápida del schema
- pgvector: Para búsqueda semántica de guías médicas
- NestJS: Para estructurar la lógica de negocio
Resultados prácticos
1. Iteración más rápida
Puedo cambiar el schema y ver los errores inmediatamente:
// Agregar un campo nuevo sin migración
export const medicalOrders = pgTable('medical_orders', {
// ... campos existentes
aiAnalysis: json('ai_analysis').$type<AiAnalysisResult>(),
priority: integer('priority').default(0)
})
2. Debugging más fácil
Los query builders son más transparentes:
// SQL generado visible durante desarrollo
console.log(
db.select()
.from(medicalOrders)
.where(eq(medicalOrders.status, 'pending'))
.toSQL()
)
3. Performance en producción
Las queries compilan a SQL optimizado y el uso de memoria es predecible.
Migration strategy
La migración de Prisma a Drizzle fue más simple de lo esperado:
Paso 1: Schema compatibility
Ambos usan TypeScript types y funciones similares. La mayor diferencia está en:
- Prisma:
@id,@default,@relation - Drizzle:
primaryKey(),defaultNow(),references()
Paso 2: Query migration
La mayoría de queries se traducen directamente:
// Prisma
await prisma.user.findMany({
include: { orders: true }
})
// Drizzle
await db
.select()
.from(users)
.leftJoin(orders, eq(users.id, orders.userId))
Paso 3: Beneficios inmediatos
- 40% menos tiempo en generación de tipos
- Queries 30% más rápidas en desarrollo
- Menos bugs por tipos incorrectos
Future proof
Drizzle está diseñado para escalar. Los planes futuros de Examya incluyen:
- Time-series data: Para análisis de tendencias médicas
- Graph features: Con pg_graphql para relaciones complejas
- Distributed transactions: Para operaciones multi-servicio
La flexibilidad de Drizzle me permite prepararse para estos escenarios sin cambiar de stack.
Conclusión: ¿Por qué Drizzle + PostgreSQL?
Para proyectos de IA, Drizzle ofrece:
- Velocidad: Iterar rápido sin fricción de tipos
- Flexibilidad: Schema evoluciona con tus necesidades
- Performance: Queries optimizadas para producción
- Type safety: Sin perder los beneficios de TypeScript
- Ecosistema: Compatible con todo el stack PostgreSQL
No es la solución perfecta para todos los casos, pero para proyectos donde los datos son dinámicos y el rendimiento crítico — como aplicaciones de IA — Drizzle ORM ha transformado mi manera de construir backends.
¿Tú usas Drizzle? ¿Cuál ha sido tu experiencia con ORMs en proyectos de IA? Déjame tu comentario en WhatsApp o X.
Si quieres ver la implementación completa, revisa el repo de Examya donde aplicamos este stack en producción con miles de queries diarias.
Lecturas relacionadas
Por temas similares
pgvector + embeddings en producción: La base de razonamiento médico en Examya
Arquitectura de búsqueda semántica y similitud textual en producción con pgvector, pg_trgm y datos MINSAL reales.
Por temas similares
Cómo instalé el primer lab PCR privado de Magallanes (y por qué terminé construyendo IA)
En marzo 2021, subí un gabinete de 300 kg con grúa al segundo piso en cuarentena patagónica. En mayo procesábamos los primeros PCR COVID privados de Magallanes. Lo que aprendí en esas noches me llevó a construir Examya.
Por temas similares
Orquestación Multi-Agente vs Agente Único: Lecciones desde el Campo
Mi viaje construyendo Cotocha: por qué la orquestación multi-agente supera al agente único en proyectos reales.