Resumen
Este stack le da a Naly un plano de control de publicación tipado: Drizzle ORM captura artículos, predicciones, fuentes, publicaciones sociales, recompensas y registros de cron como entidades relacionales en Neon Postgres, en lugar de estado de ejecución disperso. Como cada paso del flujo se guarda como filas explícitas y estados enum, Naly puede volver a ejecutar pipelines de cron de forma segura, recuperarse de fallos parciales y mantener los datos de la interfaz editorial alineados con el estado visible por la API. A fecha de 26 de junio de 2026, este es el contrato operativamente duradero del proyecto para la publicación de predicciones.
Dónde se ubica en Naly
En el stack actual, el comportamiento de publicación se comparte entre varias rutas y trabajos cron de Next.js, todos los cuales resuelven al mismo contrato de base de datos. El conjunto de paquetes actualmente en uso—next@16.0.7, react@19.2.1, drizzle-orm@^0.44.7, @neondatabase/serverless@^1.0.2, tsx@^4.21.0, typescript@^5.9.3—coincide con una capa ORM de tipo serverful ejecutándose dentro de rutas/acciones del lado del servidor y workers programados.
Naly guarda estos dominios como tablas de primera clase:
- artículos y registros de predicción
- URLs de origen y instantáneas de procedencia
- publicaciones sociales + metadatos de distribución
- puntuaciones de recompensa, metadatos de calibración y campos de auditoría
- metadatos de ejecución de cron y puntos de control de publicación
El valor no es solo persistencia; son semánticas compartidas. Cada renderizador, worker y acción de API lee el mismo modelo de estado de publicación y puede coordinarse sin banderas ocultas entre procesos.
Mecanismo técnico
Drizzle ofrece un enfoque “schema-first” para este tipo de semántica compartida. Las guías de Drizzle muestran el flujo canónico: definir el esquema en TypeScript, configurar un DATABASE_URLde Neon's drizzle, inicializarlo y usar tipos de consulta generados para inserciones/lecturas/actualizaciones (overview docs, Neon tutorial).
Un patrón mínimo de inicialización de driver al estilo Naly se ve así:
import { drizzle } from 'drizzle-orm/neon-http';
import { pgTable, text, timestamp, pgEnum, integer } from 'drizzle-orm/pg-core';
export const publicationState = pgEnum('publication_state', [
'queued', 'draft_ready', 'published', 'failed',
]);
export const publications = pgTable('publications', {
id: text('id').primaryKey(),
slug: text('slug').notNull().unique(),
state: publicationState('state').notNull(),
stateVersion: integer('state_version').notNull().default(1),
stateChangedAt: timestamp('state_changed_at').notNull().defaultNow(),
});
const db = drizzle(process.env.DATABASE_URL!);
Esto refleja las guías de Drizzle que admiten drizzle-orm/neon-http y drizzle-orm/neon-serverless como opciones de transporte para Neon, con HTTP para cargas de trabajo de una sola ejecución y comportamiento de sesión tipo WebSocket para transacciones interactivas cuando se necesita. Las pg-core de Drizzle también permiten inferencia tipada ($inferInsert, $inferSelect) para que las cargas de publicación se validen en TypeScript en tiempo de compilación, manteniendo JSON flexible para metadatos no críticos.
Para Naly, el patrón arquitectónico clave es este:
- definir transiciones de estado (
queued -> drafted -> approved -> published -> archived) como filas explícitas, - mantener la lógica de transición en un solo módulo de servidor,
- registrar cada mutación con claves de idempotencia (id de trabajo + hash de estado),
- ejecutar transiciones críticas dentro de transacciones de base de datos cuando la atomicidad importa,
- generar artefactos inmutables (por ejemplo, URLs de blob, texto social, snapshots de esquema) solo después de avanzar el estado.
El efecto es similar a una pequeña máquina de estados finita persistida en Postgres con contratos de esquema estrictos en lugar de un comportamiento implícito dentro de los workers de cron.
Lo que dice la literatura
La documentación principal presenta esto como una elección de diseño práctica para sistemas serverless:
- Drizzle se presenta como SQL-like por diseño y listo para serverless, reduciendo la sobrecarga de abstracción del ORM para equipos que quieren semántica SQL directa mientras conservan seguridad de tipos (Drizzle overview).
- Los tutoriales de Drizzle/Neon admiten explícitamente combinaciones nativas de drivers HTTP/WebSocket de Neon y modelado con esquema tipado primero, incluyendo
@neondatabase/serverlessde integración y ejemplos de inferencia de tipos (Drizzle with Neon, Get Started with Drizzle + Neon). - La matriz de conexión de Drizzle muestra separación explícita de controladores en runtime, para que los equipos puedan ajustar el modo de ejecución a la carga de trabajo y a las restricciones de runtime (Database connection docs).
- La propia documentación de drivers de Neon y sus guías de edge enfatizan que el acceso serverless/Postgres suele lograrse mediante HTTP o proxying basado en websocket, y justamente por eso las decisiones de ejecución en edge deben ser explícitas por carga de trabajo (Neon serverless driver, How to use Postgres at the edge).
En el lado del esquema, la investigación sobre evolución de esquemas muestra por qué importan los modelos de estado y las migraciones explícitas. Tesseract sostiene que la evolución de esquemas puede tratarse como una operación transaccional de primera clase y que los sistemas robustos deberían minimizar el tiempo de inactividad por diseño (online schema evolution). EvoSchema muestra que los cambios de esquema —especialmente perturbaciones a nivel de tabla— pueden desestabilizar comportamientos aguas abajo, por lo que es una advertencia fuerte contra adiciones caseras y superficiales en tablas de publicación/estado (EvoSchema).
Compromisos de diseño
La elección de Naly es, en la práctica, un intercambio entre estrictez y fricción. Los esquemas fuertemente tipados y los enums de estado explícitos mejoran observabilidad y fiabilidad, pero también incrementan el costo inicial de modelado y exigen disciplina de migraciones. La curva de intercambio es favorable cuando la lógica de publicación se comparte entre workers de cron, pipelines de IA y renderizadores de páginas públicas.
- Elección de controlador:
neon-httpes más simple y con frecuencia más rápido para operaciones de una sola ejecución;neon-serverlesses mejor cuando se requieren sesiones interactivas. - Diseño schema-first: la seguridad en tiempo de compilación reduce errores de runtime, pero los cambios de esquema requieren planificación de migraciones y pueden aparecer como despliegues bloqueados si las pruebas no cubren transiciones de estado.
- Portabilidad de runtime: el modelo de drivers de Neón amigable con edge amplía opciones de despliegue, pero el modo de transporte afecta comportamiento de sesión, perfil de latencia y ruta de autenticación/TLS.
- Fidelidad de tipos vs conveniencia operativa: los enums explícitos evitan estados inválidos, pero pueden ralentizar hotfixes nocturnos si los scripts de migración no están preaprobados.
Modos de fallo
- Controlador inadecuado para la carga: usar consultas HTTP de una sola ejecución para transiciones de estado multi-paso puede perder garantías atómicas y producir estados de publicación parciales.
- Desviación de esquema entre workers y despliegues: si
publication_statelos valores cambian sin migraciones coordinadas, el código de cron antiguo puede escribir estados inválidos. - Reintentos no idempotentes: los reinicios de cron pueden duplicar escrituras sociales a menos que los puntos de control sean idempotentes y únicos por run-id.
- Retraso de migración: los trabajos programados que ejecutan contra snapshots de esquema obsoletos pueden fallar, especialmente durante despliegues graduales.
- Arranque en frío en edge + overhead de autenticación: en capas edge restringidas, la configuración repetida de conexión puede aumentar la latencia y generar falsos timeouts si no se afinan los presupuestos de timeout y el fanout de jobs.
Para este tema, el análisis de fallos debe tratar el estado de publicación como un artefacto de corrección, no como un detalle de implementación. Cada transición de estado debe ser segura para reproducirse (replay-safe).
Notas de implementación
- Mantén los archivos de esquema centralizados y versionados; regenera los artefactos de migración desde una única fuente de verdad.
- Separa tablas de dominio mutables de tablas de artefactos inmutables.
- Modela las transiciones de publicación como un límite transaccional y aplica invariantes (por ejemplo, sin
queued -> publishedsaltos directos). - Almacena los metadatos del programador (
last_run,next_run_at,error_count) en su propia tabla para alertas y auditoría. - Prefiere módulos únicamente de servidor para inicializar la BD (
DATABASE_URLdesde.env.localen entornos de cron/runtime). - Usa consultas estructuradas sobre SQL sin procesar para la mayoría de operaciones y reserva SQL sin procesar para semillas de migración o reporting.
- Trata los
stateVersiony registros de eventos como puentes de compatibilidad cuando el esquema evoluciona.
Referencias
- Drizzle ORM - Drizzle with Neon Postgres
- Drizzle ORM Overview
- Drizzle ORM - Database connection
- Get Started with Drizzle and Neon
- Neon serverless driver (Neon Docs)
- Neon blog: How to use Postgres at the Edge
- Online Schema Evolution is (Almost) Free for Snapshot Databases
- EvoSchema: Towards Text-to-SQL Robustness Against Schema Evolution