- La clave de la ejecución durable no es la infraestructura en sí, sino la preservación del estado del flujo de trabajo; si se conserva el progreso, es posible reejecutar y recuperar
- Obelisk guarda el progreso del flujo de trabajo en un log de ejecución y lo reproduce desde el historial persistido, con una estructura adaptada al reintento de actividades
- SQLite ofrece estado durable basado en transacciones en un archivo local, sin un servicio de base de datos separado, saltos de red ni un plano de control adicional
- Litestream transmite de forma asíncrona los cambios de SQLite a un almacenamiento de objetos compatible con S3, pero si el volumen desaparece antes de la copia, se pueden perder las escrituras más recientes
- Obelisk también soporta Postgres, que resulta más adecuado cuando se necesita mayor disponibilidad, escalabilidad compartida o características propias de una base de datos en red
Modelo operativo de SQLite y Litestream
- Litestream puede transmitir de forma asíncrona los cambios de SQLite a un almacenamiento de objetos compatible con S3
- Permite mantener el estado de trabajo cerca del entorno de ejecución y, al mismo tiempo, copiar la base de datos hacia afuera para respaldos, migraciones o inspección
- Debido a la naturaleza de la replicación asíncrona, si el volumen de SQLite desaparece antes de copiarse, al restaurar se pueden perder las escrituras locales más recientes
- La estructura consiste en ejecutar el servidor de Obelisk junto con la base de datos SQLite, respaldarlo con Litestream y hacer que un observador obtenga la base de datos necesaria cuando haga falta
- El mismo archivo SQLite puede usarse para reproducción local, depuración y para entender qué hizo realmente el agente
Casos adecuados de uso y criterios para elegir Postgres
- Los agentes de IA y los flujos de trabajo generados por IA suelen ser ráfagos y, en muchos casos, experimentales, por lo que una configuración con pequeñas unidades de estado propias por agente o por tenant es más fácil de entender
- Tener varios servidores pequeños dentro de micro-VMs o contenedores, cada uno con su propia base de datos SQLite y respaldo en almacenamiento de objetos, puede ser más simple, más barato y ofrecer mejor aislamiento de fallos que un único sistema grande, compartido y siempre en ejecución
- Si la replicación asíncrona hacia almacenamiento de objetos no encaja con el modelo de durabilidad deseado, o si se necesita mayor disponibilidad, una escalabilidad compartida más amplia o características de una base de datos en red, Postgres es más apropiado
- Muchos sistemas de flujos de trabajo no necesitan ese nivel de infraestructura desde el primer día, y no hace falta empezar con una infraestructura mayor que los requisitos del estado
- Con solo una base de datos SQLite local, respaldo de Litestream hacia S3 y una combinación de workers de bajo costo, se puede construir un sistema durable con poca infraestructura, y en el ámbito de los agentes de IA puede ser una opción razonable por defecto
¿Quieres seguir recibiendo temas de tecnología seleccionados?
Sigue el canal de Telegram.
@GeekNewsES
1 comentarios
Comentarios de Hacker News
Empecé a armar flujos de trabajo con Temporal y, para una app local, se despliega de forma bastante ligera; en instalaciones locales aisladas usa SQLite
Manejar reintentos de API y la limpieza de flujos de trabajo y tareas se volvió realmente simple, así que recomendaría probarlo. Filosóficamente, va exactamente en la misma dirección que propone este artículo, pero además le suma una interfaz muy rica y flexible que resulta muy cómoda para que la manejen agentes. También es fácil revisar los flujos de trabajo en la interfaz web e inspeccionar la ejecución de agentes
Temporal le agrega al sistema un nivel de confiabilidad mucho mayor casi gratis. Los sistemas distribuidos y confiables son difíciles, así que me parece mejor no reinventar la rueda
Si quieres poder inspeccionar fácilmente una base de datos SQLite, entender qué está pasando en un flujo de trabajo, componer tareas individuales y hacer que un flujo de trabajo se pueda invocar de forma simple, vale la pena mirar Temporal
Junto con eso, casi dejé de usar archivos para agentes. Markdown y JSON están bien, pero al crear apps locales pequeñas se sienten como una trampa. Los LLM manejan bien SQLite, y desde ahí puedes renderizar a Markdown, JSON o cualquier otro formato que quieras. Si el agente puede consultar solo filas específicas en vez de levantar jq o hacer grep sobre Markdown, también ahorras muchos tokens. Obtienes un sistema de gestión de datos portátil y autocontenido que además te obliga a dar una estructura más disciplinada a los datos en vez de repartirlos entre varios archivos. Y si un proyecto local pequeño crece o se formaliza más, también puede pasar a MySQL/Postgres, ya con esquema y disciplina de datos establecidos
Temporal se vuelve mucho más complejo cuando escala. Operar Cassandra no es nada agradable, y Ringpop y TChannel son difíciles de depurar cuando surge algún problema. El soporte de backend SQL no admite réplicas con escalado horizontal por los requisitos de consistencia, así que solo es posible una única instancia
Dependiendo de cómo escribas el código, también se vuelve complejo modificar código incrustado en los flujos de trabajo. Los cambios que alteran el orden de eventos del historial rompen el determinismo de workers ya desplegados
Nosotros usamos mucho Temporal; a todos los que empezaron con scripting simple o automatización les encanta, y a todos los que construyeron sistemas reales de producción encima les desagrada. Puede ser falta de madurez operativa, pero la imagen tan color de rosa que se ve en estos comentarios no coincidió con mi experiencia
No lo he hecho personalmente, pero me gustaría escuchar más experiencias reales
No entiendo la obsesión con usar SQLite en apps reales de producción. SQLite es una base de datos embebida, así que no encaja en absoluto para manejar concurrencia
Para eso existen servidores de bases de datos como Postgres o MySQL. Todo su propósito es permitir que múltiples procesos modifiquen datos al mismo tiempo desde distintas máquinas
Este es un principio básico de la informática, así que quienes repiten “SQLite para todo” parecen tener algo de falta de experiencia
SQLite es una excelente base de datos de producción para muchas cargas de trabajo reales, y eso está ampliamente documentado. Como es muy diferente de Postgres, hay que aprender una tecnología completamente distinta
Una forma de verlo es que SQLite puede encajar muy bien en partes de un sistema donde de forma natural hay una partición fuerte
net/httpde Go, muchas veces basta para manejar toda la carga que un servicio pueda imaginar. Más aún si con el tiempo puedes escalar el hardware, y SQLite puede escalar fácilmente hasta cientos de miles de TPSLo que realmente se sacrifica es alta disponibilidad/failover y recuperación ante desastres, aunque también hay soluciones para eso. Los sistemas de servidor único suelen ser sorprendentemente robustos, porque cuando no hay un plano de control complejo, muchas veces la disponibilidad baja a medida que el sistema crece
Me gusta reevaluar las “mejores prácticas” tradicionales a la luz de los cambios tecnológicos, sobre todo si eso aumenta la simplicidad. Tener un sitio de redes sociales familiar corriendo sobre una sola DB SQLite en un VPS es excelente. Son como 15 usuarios y casi no requiere mantenimiento. También tengo una instancia de FreshRSS y una página “now” corriendo sobre SQLite
En el trabajo también he usado SQLite para todo tipo de cosas durante las últimas décadas. Lo he usado para colas de trabajo temporales, para cargar y consultar rápidamente muchos logs en local, y para mostrarlos y filtrarlos en tiempo real con el excelente https://github.com/simonw/datasette de simonw
Más que “SQLite para todo”, yo lo vería como “SQLite para muchas más cosas de las que uno cree”
El trabajo de kentonv/Cloudflare con SQLite en el edge puede haber popularizado un poco más esta idea, pero la tendencia ya existía. https://blog.cloudflare.com/sqlite-in-durable-objects/
Querer conocer y aprovechar estos casos pequeños pero útiles no es falta de experiencia; de hecho, puede ser una señal de experiencia
Es muy probable que SQLite se use más que todos los demás motores de bases de datos juntos. Hay miles de millones de copias de SQLite en el mundo real. Está en dispositivos Android, iPhone y otros equipos iOS, Mac, instalaciones de Windows 10/11, Firefox/Chrome/Safari, Skype, iTunes, el cliente de Dropbox, TurboTax y QuickBooks, PHP y Python, la mayoría de las TVs y set-top boxes, la mayoría de los sistemas multimedia de autos y en una cantidad incontable de aplicaciones
https://sqlite.org/mostdeployed.html
Eso hace que la escalabilidad sea mucho más fácil de entender. Solo hay que dividir y repetir; agregas un shard más cada N usuarios
A cambio obtienes otros problemas, como consultas entre shards, por ejemplo para analítica, y cómo nivelar la carga cuando los usuarios se van o envejecen
Pero sí puedes evitar todo el problema de escalar índices compartidos generados por inserciones/actualizaciones cuando tienes una gran cantidad de usuarios
Termina siendo más una base de datos jerárquica que una base de datos relacional
Reemplazó todo esto con Go + SQLite: Intercom, Zendesk, email marketing, Kanban, Todo, stack de pagos, issue tracker, foro, monitor de uptime, clon de PagerDuty
Como vende decenas de productos, pensó: ¿y si construyo todo yo mismo?
Todo corre en el mismo servidor y usa muy poca memoria. Reemplazó por completo las herramientas SaaS que usaba con estas alternativas
Al migrar a un servidor dedicado, bajó el costo a cerca de 1/10 de lo que pagaba por soluciones cloud administradas, con la misma alta disponibilidad y además menor latencia. Parte del motivo era que los noisy neighbors en el VPS aumentaban la tail latency
Antes gastaba mucho dinero en estas cosas, pero ya lleva 4 meses operándolo y solo ha necesitado actualizaciones menores
El despliegue es realmente simple. Sin Docker ni Kubernetes, solo servicios de systemd y binarios compilados en la máquina de desarrollo y luego desplegados
También pagaba por servicios como MaxMind o IPData, pero creó su propio servicio de geolocalización IP y en pruebas rindió mejor que la mayoría de las soluciones existentes
Empezó reemplazando Uptime Robot, luego ganó confianza y reemplazó PagerDuty. Después reemplazó Intercom
Por último, siempre había escuchado “no construyas tu propio stack de pagos”, pero pensó YOLO y decidió cometer ese error por su cuenta. Estudió las soluciones de pago existentes, desarrolló y desplegó la suya, y hasta ahora no ha tenido ningún problema
Delante puso Caddy
Se dio cuenta de que, de lo que ofrecen la mayoría de los productos SaaS, en realidad solo usaba entre 1% y 5%, y que justo las funciones que sí necesitaba quedaban cada vez más enterradas dentro de estas plataformas “enterprise”, dificultando el flujo de trabajo
No va a mostrar los productos comerciales porque a sus socios y clientes probablemente no les gustaría saber lo barato que le sale, pero él lo llama ser ingenioso
Sí puede mostrar una app gratuita. La lanzó recientemente y ya tiene más de 20 mil usuarios: https://macrocodex.app/
Esta app solo usa el clon de Zendesk. El email lo maneja con enrutamiento de Cloudflare, así que el costo operativo es casi nulo
Hay una gran distancia entre un archivo y una base de datos con múltiples particiones. No es de mi gusto correr una base de datos en contenedores cuando hay producción real de por medio
Personalmente, mucho ETL puede procesarse localmente sin traer una base de datos enterprise. En esos casos, DuckDB es entre 5 y 10 veces mejor que SQLite, y mucho más simple y rápido que levantar una base de datos Postgres dedicada
Para scripting general, no hay comparación entre un script de awk de 20 líneas y su equivalente en SQL sobre DuckDB, mucho más limpio, robusto y mantenible
Ojalá MotherDuck no termine haciendo pump and dump para llegar a un IPO. Sería triste perder esta herramienta por la típica codicia corporativa
Lo del script de awk de 20 líneas es interesante. Ayer en Ubuntu Summit hice casi el mismo argumento. A partir de cierto punto, escribir shell scripts con GNU coreutils se vuelve poco realista, y los scripts SQL en DuckDB escalan mucho mejor en complejidad, mantenibilidad y, a menudo, también en rendimiento. Las diapositivas están aquí: https://blobs.duckdb.org/slides/duckdb-ubuntu-summit-2026.pd... páginas 32–36
Además, MotherDuck desarrolla un DBaaS de código cerrado sobre DuckDB. Está construido sobre DuckDB, y DuckDB puede conectarse a MotherDuck, pero es una empresa separada con inversión de VC y sede en Seattle
DuckDB lo desarrolla DuckLabs, una empresa bootstrappeada de Ámsterdam, es decir, basada en ingresos. La propiedad intelectual del proyecto pertenece a una tercera organización, la fundación neerlandesa sin fines de lucro DuckDB Foundation. Más detalles en https://duckdb.org/faq#how-are-duckdb-the-duckdb-foundation-...
Creé una librería[0] que permite hacer actualizaciones concurrentes de forma segura sobre una DB SQLite en S3
Usa la poco conocida extensión SQLite sessions y compare-and-swap de S3 sobre un pequeño archivo de metadatos para lograr un funcionamiento bastante eficiente y seguro. La uso con gusto en varios proyectos pequeños donde necesito una DB con estado para funciones Lambda, pero no quiero pagar el costo de una instancia completa de base de datos
[0]: https://github.com/psanford/s3db
SQLite tiene un rendimiento sorprendentemente bueno frente a Postgres en aplicaciones de un solo nodo
Postgres usa mucha más memoria y la E/S tiene que pasar por comunicación entre procesos. SQLite, en cambio, puede mantener todo dentro del proceso mediante un pool de conexiones compartido
Estoy probando varios motores de almacenamiento para un agent harness, y con SQLite pude llegar a 7.5 mil sesiones concurrentes en un solo vCPU, mientras que Postgres se caía o se quedaba sin conexiones
[0] https://github.com/impalasys/talon/pull/23#issuecomment-4577...
En cuanto sales del hilo actual, ya es una batalla perdida en términos de latencia. Si no fuerzas comunicación entre hilos, SQLite puede operar en escalas de microsegundos
En el contexto de un solo nodo, Postgres es demasiado. No debería esperarse que compita con SQLite
Es casi como benchmarkear un HashMap en memoria contra Redis y sorprenderse de que el HashMap salga mejor en condiciones ideales
Después de leer sobre SQLite durante años, lo probé en un proyecto personal y, viniendo de usar Postgres, me impactó lo pobre que es su sistema de tipos
De verdad es muy inferior, no entiendo por qué recibe tantos elogios
https://sqlite.org/datatype3.html
https://www.postgresql.org/docs/current/datatype.html
La experiencia al manejar fechas/horas se siente como usar una base de datos de hace 30 años, y al insertar no se fuerza prácticamente nada. Alguien tendría que explicar por qué a tanta gente le gusta
PRAGMA journal_mode = WAL
PRAGMA foreign_keys = ON
Something non-null
PRAGMA busy_timeout = 1000This is fine for most applications, but see the manual
PRAGMA synchronous = NORMALIf you use it as a file format
PRAGMA trusted_schema = OFFDependiendo del binding, puede que hagan falta opciones adicionales. Por ejemplo, una aplicación en Python no debería usar los valores por defecto del módulo sqlite3. Esos valores por defecto están simplemente mal. Antes de 3.12 ni siquiera había alternativa aparte de usar un binding fuera de la biblioteca estándar: https://docs.python.org/3/library/sqlite3.html#transaction-c...
También hay que usar tablas strict. https://www.sqlite.org/stricttables.html
La usabilidad es mala, pero también se pueden usar restricciones CHECK. Por ejemplo, con el soporte de fechas integrado de SQLite se puede, pero es incómodo:
CHECK (
date(my_date_col) IS NOT NULL
AND my_date_col = date(my_date_col)
)
Se necesita el IS NOT NULL porque date devuelve NULL con fechas inválidas. La otra verificación es porque también acepta días julianos; por ejemplo, date('2026') se convierte en algún momento del año 4707 a. C.
En especial antes de las tablas strict, coincido en que era decepcionante
Hay que ver DuckDB. Se acerca a SQLite pero con tipos de verdad. Eso sí, en lugar de OLTP, o sea arreglo de structs, es OLAP, o sea struct de arreglos, así que bajo cargas típicas de SQLite podría rendir peor. En la práctica, si una aplicación está considerando una u otra, probablemente no haya una gran diferencia
Después de usar varios clústeres grandes de Postgres, me cambié a SQLite, y un servicio con 7 cifras de usuarios activos mensuales está sostenido por durable objects de SQLite
Hay que pensar distinto los patrones de acceso, pero las ventajas valieron totalmente la pena
Es un buen encuadre. Si el problema principal es almacenar de forma durable el estado del flujo de trabajo, poder inspeccionarlo y recuperarlo fácilmente, muchas veces SQLite basta
Tengo ganas de ver pronto la siguiente iteración de esta idea: “para flujos de trabajo durables solo hace falta un log”
Una razón por la que una solución del tipo “solo hace falta un log” puede fallar es cuando un log no confiable se convierte en un ataque por inyección[1]
Hay que revisar el SBOM, y no olvidar incluir también el pipeline de CI/CD[2]
[1] https://news.ycombinator.com/item?id=48315440
[2] https://github.com/jqwik-team/jqwik/issues/708#issuecomment-...
Hablando en serio, ser experto es usar la herramienta adecuada para el trabajo